summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.appveyor.yml15
-rw-r--r--.travis.yml2
-rw-r--r--core/bind/core_bind.cpp17
-rw-r--r--core/bind/core_bind.h3
-rw-r--r--core/class_db.cpp7
-rw-r--r--core/engine.cpp4
-rw-r--r--core/io/file_access_pack.cpp14
-rw-r--r--core/io/file_access_pack.h5
-rw-r--r--core/io/marshalls.cpp12
-rw-r--r--core/io/pck_packer.cpp11
-rw-r--r--core/io/resource_loader.cpp5
-rw-r--r--core/object.cpp16
-rw-r--r--core/os/os.cpp6
-rw-r--r--core/os/os.h2
-rw-r--r--core/project_settings.cpp10
-rw-r--r--core/resource.cpp5
-rw-r--r--core/version.h17
-rw-r--r--doc/classes/Array.xml7
-rw-r--r--doc/classes/ArrayMesh.xml2
-rw-r--r--doc/classes/AudioStreamPlayer.xml2
-rw-r--r--doc/classes/AudioStreamPlayer2D.xml2
-rw-r--r--doc/classes/AudioStreamPlayer3D.xml2
-rw-r--r--doc/classes/BaseButton.xml1
-rw-r--r--doc/classes/CPUParticles.xml3
-rw-r--r--doc/classes/CPUParticles2D.xml3
-rw-r--r--doc/classes/CanvasItem.xml1
-rw-r--r--doc/classes/CollisionObject2D.xml2
-rw-r--r--doc/classes/ColorPickerButton.xml2
-rw-r--r--doc/classes/Control.xml2
-rw-r--r--doc/classes/Crypto.xml1
-rw-r--r--doc/classes/CryptoKey.xml1
-rw-r--r--doc/classes/Directory.xml1
-rw-r--r--doc/classes/Engine.xml19
-rw-r--r--doc/classes/Environment.xml173
-rw-r--r--doc/classes/Font.xml1
-rw-r--r--doc/classes/Geometry.xml2
-rw-r--r--doc/classes/GeometryInstance.xml2
-rw-r--r--doc/classes/GraphEdit.xml22
-rw-r--r--doc/classes/GraphNode.xml23
-rw-r--r--doc/classes/HScrollBar.xml11
-rw-r--r--doc/classes/HashingContext.xml1
-rw-r--r--doc/classes/Image.xml17
-rw-r--r--doc/classes/InputMap.xml1
-rw-r--r--doc/classes/KinematicBody.xml15
-rw-r--r--doc/classes/KinematicBody2D.xml15
-rw-r--r--doc/classes/Light.xml18
-rw-r--r--doc/classes/LineEdit.xml22
-rw-r--r--doc/classes/MainLoop.xml3
-rw-r--r--doc/classes/Mesh.xml25
-rw-r--r--doc/classes/MeshInstance.xml1
-rw-r--r--doc/classes/MeshInstance2D.xml1
-rw-r--r--doc/classes/MultiMesh.xml5
-rw-r--r--doc/classes/MultiMeshInstance.xml1
-rw-r--r--doc/classes/MultiMeshInstance2D.xml1
-rw-r--r--doc/classes/NinePatchRect.xml4
-rw-r--r--doc/classes/OS.xml16
-rw-r--r--doc/classes/Object.xml3
-rw-r--r--doc/classes/OmniLight.xml2
-rw-r--r--doc/classes/ParticlesMaterial.xml3
-rw-r--r--doc/classes/PoolByteArray.xml5
-rw-r--r--doc/classes/PopupMenu.xml2
-rw-r--r--doc/classes/ProjectSettings.xml4
-rw-r--r--doc/classes/RichTextLabel.xml26
-rw-r--r--doc/classes/ScriptCreateDialog.xml2
-rw-r--r--doc/classes/ScrollBar.xml1
-rw-r--r--doc/classes/ShaderMaterial.xml2
-rw-r--r--doc/classes/SpinBox.xml7
-rw-r--r--doc/classes/SplitContainer.xml13
-rw-r--r--doc/classes/SpriteFrames.xml1
-rw-r--r--doc/classes/StreamPeerSSL.xml1
-rw-r--r--doc/classes/StyleBox.xml8
-rw-r--r--doc/classes/TabContainer.xml1
-rw-r--r--doc/classes/Tabs.xml15
-rw-r--r--doc/classes/TextEdit.xml6
-rw-r--r--doc/classes/Texture3D.xml2
-rw-r--r--doc/classes/Thread.xml3
-rw-r--r--doc/classes/Tree.xml47
-rw-r--r--doc/classes/VScrollBar.xml12
-rw-r--r--doc/classes/VisibilityEnabler.xml2
-rw-r--r--doc/classes/VisibilityEnabler2D.xml3
-rw-r--r--doc/classes/VisualInstance.xml9
-rw-r--r--doc/classes/VisualServer.xml344
-rw-r--r--doc/classes/VisualShaderNodeFresnel.xml2
-rw-r--r--doc/classes/X509Certificate.xml1
-rw-r--r--doc/classes/bool.xml33
-rw-r--r--doc/classes/float.xml2
-rwxr-xr-xdoc/tools/makerst.py29
-rw-r--r--drivers/dummy/rasterizer_dummy.h2
-rw-r--r--drivers/gles2/rasterizer_canvas_gles2.cpp2
-rw-r--r--drivers/gles2/rasterizer_gles2.cpp3
-rw-r--r--drivers/gles2/rasterizer_scene_gles2.cpp6
-rw-r--r--drivers/gles2/rasterizer_storage_gles2.cpp55
-rw-r--r--drivers/gles2/rasterizer_storage_gles2.h2
-rw-r--r--drivers/gles2/shader_compiler_gles2.cpp19
-rw-r--r--drivers/gles2/shaders/scene.glsl26
-rw-r--r--drivers/gles3/rasterizer_canvas_gles3.cpp4
-rw-r--r--drivers/gles3/rasterizer_gles3.cpp3
-rw-r--r--drivers/gles3/rasterizer_scene_gles3.cpp10
-rw-r--r--drivers/gles3/rasterizer_storage_gles3.cpp26
-rw-r--r--drivers/gles3/rasterizer_storage_gles3.h2
-rw-r--r--drivers/gles3/shaders/cubemap_filter.glsl2
-rw-r--r--drivers/unix/os_unix.cpp32
-rw-r--r--editor/animation_track_editor.cpp5
-rw-r--r--editor/code_editor.cpp4
-rw-r--r--editor/connections_dialog.cpp47
-rw-r--r--editor/connections_dialog.h2
-rw-r--r--editor/create_dialog.cpp17
-rw-r--r--editor/editor_asset_installer.cpp8
-rw-r--r--editor/editor_audio_buses.cpp2
-rw-r--r--editor/editor_data.cpp2
-rw-r--r--editor/editor_export.cpp56
-rw-r--r--editor/editor_feature_profile.cpp10
-rw-r--r--editor/editor_help.cpp132
-rw-r--r--editor/editor_node.cpp114
-rw-r--r--editor/editor_node.h12
-rw-r--r--editor/editor_properties.cpp13
-rw-r--r--editor/editor_properties.h4
-rw-r--r--editor/editor_resource_preview.cpp2
-rw-r--r--editor/editor_themes.cpp2
-rw-r--r--editor/filesystem_dock.cpp13
-rw-r--r--editor/groups_editor.cpp12
-rw-r--r--editor/icons/icon_audio_stream_o_g_g_vorbis.svg1
-rw-r--r--editor/icons/icon_crosshair.svg1
-rw-r--r--editor/import/editor_scene_importer_gltf.cpp14
-rw-r--r--editor/import/editor_scene_importer_gltf.h1
-rw-r--r--editor/import/resource_importer_obj.cpp14
-rw-r--r--editor/plugins/animation_player_editor_plugin.cpp2
-rw-r--r--editor/plugins/animation_tree_editor_plugin.cpp3
-rw-r--r--editor/plugins/asset_library_editor_plugin.cpp4
-rw-r--r--editor/plugins/audio_stream_editor_plugin.cpp3
-rw-r--r--editor/plugins/canvas_item_editor_plugin.cpp52
-rw-r--r--editor/plugins/cpu_particles_2d_editor_plugin.cpp6
-rw-r--r--editor/plugins/item_list_editor_plugin.cpp2
-rw-r--r--editor/plugins/particles_2d_editor_plugin.cpp6
-rw-r--r--editor/plugins/polygon_2d_editor_plugin.cpp11
-rw-r--r--editor/plugins/resource_preloader_editor_plugin.cpp3
-rw-r--r--editor/plugins/script_editor_plugin.cpp4
-rw-r--r--editor/plugins/script_text_editor.cpp14
-rw-r--r--editor/plugins/shader_editor_plugin.cpp3
-rw-r--r--editor/plugins/spatial_editor_plugin.cpp15
-rw-r--r--editor/plugins/spatial_editor_plugin.h1
-rw-r--r--editor/plugins/texture_region_editor_plugin.cpp67
-rw-r--r--editor/plugins/tile_set_editor_plugin.cpp28
-rw-r--r--editor/plugins/visual_shader_editor_plugin.cpp2
-rw-r--r--editor/project_export.cpp27
-rw-r--r--editor/project_manager.cpp1
-rw-r--r--editor/script_create_dialog.cpp55
-rw-r--r--editor/script_create_dialog.h4
-rw-r--r--editor/translations/af.po77
-rw-r--r--editor/translations/ar.po84
-rw-r--r--editor/translations/bg.po77
-rw-r--r--editor/translations/bn.po86
-rw-r--r--editor/translations/ca.po112
-rw-r--r--editor/translations/cs.po168
-rw-r--r--editor/translations/da.po84
-rw-r--r--editor/translations/de.po144
-rw-r--r--editor/translations/de_CH.po70
-rw-r--r--editor/translations/editor.pot68
-rw-r--r--editor/translations/el.po112
-rw-r--r--editor/translations/eo.po74
-rw-r--r--editor/translations/es.po184
-rw-r--r--editor/translations/es_AR.po156
-rw-r--r--editor/translations/et.po68
-rw-r--r--editor/translations/eu.po68
-rwxr-xr-xeditor/translations/extract.py5
-rw-r--r--editor/translations/fa.po84
-rw-r--r--editor/translations/fi.po162
-rw-r--r--editor/translations/fil.po68
-rw-r--r--editor/translations/fr.po146
-rw-r--r--editor/translations/ga.po69
-rw-r--r--editor/translations/he.po80
-rw-r--r--editor/translations/hi.po70
-rw-r--r--editor/translations/hr.po70
-rw-r--r--editor/translations/hu.po84
-rw-r--r--editor/translations/id.po86
-rw-r--r--editor/translations/is.po68
-rw-r--r--editor/translations/it.po89
-rw-r--r--editor/translations/ja.po170
-rw-r--r--editor/translations/ka.po70
-rw-r--r--editor/translations/ko.po144
-rw-r--r--editor/translations/lt.po69
-rw-r--r--editor/translations/lv.po69
-rw-r--r--editor/translations/mi.po68
-rw-r--r--editor/translations/ml.po68
-rw-r--r--editor/translations/mr.po76
-rw-r--r--editor/translations/ms.po68
-rw-r--r--editor/translations/nb.po87
-rw-r--r--editor/translations/nl.po235
-rw-r--r--editor/translations/or.po68
-rw-r--r--editor/translations/pl.po144
-rw-r--r--editor/translations/pr.po69
-rw-r--r--editor/translations/pt_BR.po145
-rw-r--r--editor/translations/pt_PT.po152
-rw-r--r--editor/translations/ro.po84
-rw-r--r--editor/translations/ru.po118
-rw-r--r--editor/translations/si.po68
-rw-r--r--editor/translations/sk.po72
-rw-r--r--editor/translations/sl.po84
-rw-r--r--editor/translations/sq.po80
-rw-r--r--editor/translations/sr_Cyrl.po81
-rw-r--r--editor/translations/sr_Latn.po68
-rw-r--r--editor/translations/sv.po84
-rw-r--r--editor/translations/ta.po68
-rw-r--r--editor/translations/te.po68
-rw-r--r--editor/translations/th.po254
-rw-r--r--editor/translations/tr.po88
-rw-r--r--editor/translations/uk.po148
-rw-r--r--editor/translations/ur_PK.po68
-rw-r--r--editor/translations/vi.po80
-rw-r--r--editor/translations/zh_CN.po351
-rw-r--r--editor/translations/zh_HK.po81
-rw-r--r--editor/translations/zh_TW.po104
-rw-r--r--main/SCsub4
-rw-r--r--main/gamecontrollerdb.txt18
-rw-r--r--main/input_default.cpp16
-rw-r--r--main/main.cpp78
-rw-r--r--main/tests/test_gdscript.cpp24
-rw-r--r--methods.py3
-rw-r--r--misc/dist/shell/_godot.zsh-completion77
-rw-r--r--modules/assimp/editor_scene_importer_assimp.cpp4
-rw-r--r--modules/assimp/import_utils.h2
-rw-r--r--modules/bullet/SCsub26
-rw-r--r--modules/bullet/space_bullet.cpp4
-rw-r--r--modules/enet/doc_classes/NetworkedMultiplayerENet.xml2
-rw-r--r--modules/enet/networked_multiplayer_enet.cpp2
-rw-r--r--modules/etc/image_etc.cpp13
-rw-r--r--modules/gdnative/gdnative/gdnative.cpp4
-rw-r--r--modules/gdnative/gdnative_api.json7
-rw-r--r--modules/gdnative/include/gdnative/gdnative.h3
-rw-r--r--modules/gdscript/gdscript.cpp57
-rw-r--r--modules/gdscript/gdscript.h9
-rw-r--r--modules/gdscript/gdscript_compiler.cpp28
-rw-r--r--modules/gdscript/gdscript_compiler.h6
-rw-r--r--modules/gdscript/gdscript_editor.cpp22
-rw-r--r--modules/gdscript/gdscript_function.cpp7
-rw-r--r--modules/gdscript/gdscript_function.h22
-rw-r--r--modules/gdscript/gdscript_functions.cpp7
-rw-r--r--modules/gdscript/gdscript_parser.cpp101
-rw-r--r--modules/gdscript/language_server/gdscript_extend_parser.cpp50
-rw-r--r--modules/gdscript/language_server/gdscript_extend_parser.h2
-rw-r--r--modules/gdscript/language_server/gdscript_language_protocol.cpp3
-rw-r--r--modules/gdscript/language_server/gdscript_language_protocol.h2
-rw-r--r--modules/gdscript/language_server/gdscript_language_server.cpp54
-rw-r--r--modules/gdscript/language_server/gdscript_language_server.h5
-rw-r--r--modules/gdscript/language_server/gdscript_text_document.cpp136
-rw-r--r--modules/gdscript/language_server/gdscript_text_document.h3
-rw-r--r--modules/gdscript/language_server/gdscript_workspace.cpp51
-rw-r--r--modules/gdscript/language_server/gdscript_workspace.h1
-rw-r--r--modules/gdscript/language_server/lsp.hpp118
-rw-r--r--modules/gridmap/grid_map.cpp2
-rw-r--r--modules/mono/csharp_script.cpp183
-rw-r--r--modules/mono/csharp_script.h8
-rw-r--r--modules/mono/glue/base_object_glue.cpp1
-rw-r--r--modules/mono/icons/icon_c_sharp_script.svg (renamed from modules/mono/icons/icon_c_#.svg)0
-rw-r--r--modules/mono/mono_gd/gd_mono_assembly.cpp6
-rw-r--r--modules/mono/mono_gd/gd_mono_internals.cpp4
-rw-r--r--modules/mono/mono_gd/gd_mono_utils.cpp36
-rw-r--r--modules/mono/mono_gd/gd_mono_utils.h23
-rw-r--r--modules/opensimplex/noise_texture.cpp12
-rw-r--r--modules/squish/image_compress_squish.cpp2
-rw-r--r--modules/squish/image_compress_squish.h2
-rw-r--r--modules/squish/register_types.cpp2
-rw-r--r--modules/stb_vorbis/doc_classes/AudioStreamOGGVorbis.xml2
-rw-r--r--modules/visual_script/visual_script_editor.cpp4
-rw-r--r--modules/websocket/doc_classes/WebSocketClient.xml4
-rw-r--r--modules/websocket/doc_classes/WebSocketServer.xml5
-rw-r--r--modules/websocket/websocket_server.cpp15
-rw-r--r--modules/websocket/websocket_server.h5
-rw-r--r--modules/websocket/wsl_server.cpp2
-rw-r--r--platform/android/dir_access_jandroid.cpp1
-rw-r--r--platform/android/export/export.cpp461
-rw-r--r--platform/android/java/app/AndroidManifest.xml2
-rw-r--r--platform/android/java/lib/AndroidManifest.xml2
-rw-r--r--platform/android/java/lib/res/drawable-nodpi/icon.pngbin7569 -> 0 bytes
-rw-r--r--platform/android/java/lib/res/mipmap-anydpi-v26/icon.xml5
-rw-r--r--platform/android/java/lib/res/mipmap-hdpi/icon.pngbin0 -> 3762 bytes
-rw-r--r--platform/android/java/lib/res/mipmap-hdpi/icon_background.pngbin0 -> 375 bytes
-rw-r--r--platform/android/java/lib/res/mipmap-hdpi/icon_foreground.pngbin0 -> 2998 bytes
-rw-r--r--platform/android/java/lib/res/mipmap-mdpi/icon.pngbin0 -> 2672 bytes
-rw-r--r--platform/android/java/lib/res/mipmap-mdpi/icon_background.pngbin0 -> 240 bytes
-rw-r--r--platform/android/java/lib/res/mipmap-mdpi/icon_foreground.pngbin0 -> 1909 bytes
-rw-r--r--platform/android/java/lib/res/mipmap-xhdpi/icon.pngbin0 -> 5186 bytes
-rw-r--r--platform/android/java/lib/res/mipmap-xhdpi/icon_background.pngbin0 -> 517 bytes
-rw-r--r--platform/android/java/lib/res/mipmap-xhdpi/icon_foreground.pngbin0 -> 4490 bytes
-rw-r--r--platform/android/java/lib/res/mipmap-xxhdpi/icon.pngbin0 -> 8154 bytes
-rw-r--r--platform/android/java/lib/res/mipmap-xxhdpi/icon_background.pngbin0 -> 905 bytes
-rw-r--r--platform/android/java/lib/res/mipmap-xxhdpi/icon_foreground.pngbin0 -> 7415 bytes
-rw-r--r--platform/android/java/lib/res/mipmap-xxxhdpi/icon.pngbin0 -> 11749 bytes
-rw-r--r--platform/android/java/lib/res/mipmap-xxxhdpi/icon_background.pngbin0 -> 1360 bytes
-rw-r--r--platform/android/java/lib/res/mipmap-xxxhdpi/icon_foreground.pngbin0 -> 11325 bytes
-rw-r--r--platform/android/java/lib/res/mipmap/icon.pngbin0 -> 11749 bytes
-rw-r--r--platform/android/java/lib/res/mipmap/icon_background.pngbin0 -> 240 bytes
-rw-r--r--platform/android/java/lib/res/mipmap/icon_foreground.pngbin0 -> 1909 bytes
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/GodotLib.java10
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/GodotView.java5
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/input/GodotGestureHandler.java106
-rw-r--r--platform/android/java_godot_lib_jni.cpp14
-rw-r--r--platform/android/java_godot_lib_jni.h2
-rw-r--r--platform/android/os_android.cpp20
-rw-r--r--platform/android/os_android.h3
-rw-r--r--platform/haiku/detect.py2
-rw-r--r--platform/iphone/export/export.cpp35
-rw-r--r--platform/javascript/export/export.cpp42
-rw-r--r--platform/osx/export/export.cpp86
-rw-r--r--platform/osx/godot_main_osx.mm29
-rw-r--r--platform/osx/os_osx.h5
-rw-r--r--platform/osx/os_osx.mm37
-rw-r--r--platform/server/detect.py2
-rw-r--r--platform/server/os_server.h1
-rw-r--r--platform/uwp/export/export.cpp49
-rw-r--r--platform/windows/context_gl_windows.cpp8
-rw-r--r--platform/windows/context_gl_windows.h2
-rw-r--r--platform/windows/godot_res.rc4
-rw-r--r--platform/windows/joypad_windows.cpp5
-rwxr-xr-xplatform/windows/os_windows.cpp13
-rw-r--r--platform/windows/os_windows.h2
-rw-r--r--platform/x11/crash_handler_x11.cpp2
-rw-r--r--platform/x11/detect.py14
-rw-r--r--platform/x11/os_x11.cpp8
-rw-r--r--platform/x11/os_x11.h2
-rw-r--r--platform/x11/pck_embed.ld4
-rw-r--r--platform/x11/pck_embed.legacy.ld10
-rw-r--r--scene/2d/animated_sprite.cpp2
-rw-r--r--scene/2d/animated_sprite.h2
-rw-r--r--scene/2d/back_buffer_copy.cpp2
-rw-r--r--scene/2d/back_buffer_copy.h2
-rw-r--r--scene/2d/canvas_item.cpp7
-rw-r--r--scene/2d/canvas_item.h3
-rw-r--r--scene/2d/collision_polygon_2d.cpp2
-rw-r--r--scene/2d/collision_polygon_2d.h10
-rw-r--r--scene/2d/cpu_particles_2d.cpp6
-rw-r--r--scene/2d/cpu_particles_2d.h1
-rw-r--r--scene/2d/light_2d.cpp6
-rw-r--r--scene/2d/light_2d.h2
-rw-r--r--scene/2d/light_occluder_2d.cpp5
-rw-r--r--scene/2d/light_occluder_2d.h4
-rw-r--r--scene/2d/line_2d.cpp2
-rw-r--r--scene/2d/line_2d.h6
-rw-r--r--scene/2d/mesh_instance_2d.cpp2
-rw-r--r--scene/2d/mesh_instance_2d.h6
-rw-r--r--scene/2d/multimesh_instance_2d.cpp2
-rw-r--r--scene/2d/multimesh_instance_2d.h6
-rw-r--r--scene/2d/navigation_polygon.cpp5
-rw-r--r--scene/2d/navigation_polygon.h4
-rw-r--r--scene/2d/node_2d.cpp4
-rw-r--r--scene/2d/node_2d.h2
-rw-r--r--scene/2d/path_2d.cpp2
-rw-r--r--scene/2d/path_2d.h2
-rw-r--r--scene/2d/physics_body_2d.cpp35
-rw-r--r--scene/2d/physics_body_2d.h6
-rw-r--r--scene/2d/polygon_2d.cpp2
-rw-r--r--scene/2d/polygon_2d.h2
-rw-r--r--scene/2d/position_2d.cpp2
-rw-r--r--scene/2d/position_2d.h2
-rw-r--r--scene/2d/sprite.cpp12
-rw-r--r--scene/2d/sprite.h6
-rw-r--r--scene/2d/tile_map.cpp2
-rw-r--r--scene/2d/tile_map.h2
-rw-r--r--scene/2d/touch_screen_button.cpp12
-rw-r--r--scene/2d/touch_screen_button.h7
-rw-r--r--scene/2d/visibility_notifier_2d.cpp19
-rw-r--r--scene/2d/visibility_notifier_2d.h2
-rw-r--r--scene/3d/camera.cpp4
-rw-r--r--scene/3d/cpu_particles.cpp6
-rw-r--r--scene/3d/cpu_particles.h1
-rw-r--r--scene/3d/physics_body.cpp46
-rw-r--r--scene/3d/physics_body.h6
-rw-r--r--scene/animation/skeleton_ik.cpp2
-rw-r--r--scene/gui/base_button.cpp2
-rw-r--r--scene/gui/center_container.cpp6
-rw-r--r--scene/gui/color_picker.cpp4
-rw-r--r--scene/gui/control.cpp16
-rw-r--r--scene/gui/control.h2
-rw-r--r--scene/gui/graph_edit.cpp28
-rw-r--r--scene/gui/item_list.cpp2
-rw-r--r--scene/gui/label.cpp34
-rw-r--r--scene/gui/line_edit.cpp26
-rw-r--r--scene/gui/rich_text_label.cpp51
-rw-r--r--scene/gui/scroll_container.cpp38
-rw-r--r--scene/gui/spin_box.cpp5
-rw-r--r--scene/gui/spin_box.h2
-rw-r--r--scene/gui/text_edit.cpp6
-rw-r--r--scene/main/node.cpp3
-rw-r--r--scene/main/viewport.cpp52
-rw-r--r--scene/main/viewport.h2
-rw-r--r--scene/register_scene_types.cpp44
-rw-r--r--scene/resources/default_theme/default_theme.cpp2
-rw-r--r--scene/resources/dynamic_font.cpp22
-rw-r--r--scene/resources/dynamic_font.h2
-rw-r--r--scene/resources/mesh.cpp4
-rw-r--r--scene/resources/packed_scene.cpp34
-rw-r--r--scene/resources/particles_material.cpp13
-rw-r--r--scene/resources/particles_material.h1
-rw-r--r--scene/resources/style_box.cpp6
-rw-r--r--scene/resources/texture.cpp2
-rw-r--r--scene/resources/visual_shader_nodes.cpp27
-rw-r--r--scene/resources/visual_shader_nodes.h1
-rw-r--r--scene/resources/world.cpp10
-rw-r--r--servers/physics/area_sw.cpp3
-rw-r--r--servers/physics_2d/area_2d_sw.cpp3
-rw-r--r--servers/visual/rasterizer.h2
-rw-r--r--servers/visual/shader_language.cpp43
-rw-r--r--servers/visual/visual_server_raster.cpp10
-rw-r--r--servers/visual/visual_server_raster.h2
-rw-r--r--servers/visual/visual_server_wrap_mt.h10
-rw-r--r--servers/visual_server.cpp2
-rw-r--r--servers/visual_server.h4
-rw-r--r--thirdparty/README.md18
-rw-r--r--thirdparty/bullet/Bullet3Common/b3Logging.h16
-rw-r--r--thirdparty/bullet/Bullet3Common/b3Scalar.h34
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/BroadphaseCollision/b3GpuParallelLinearBvh.cpp2
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3StridingMeshInterface.h2
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3TriangleIndexVertexArray.h2
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3VoronoiSimplexSolver.cpp4
-rw-r--r--thirdparty/bullet/BulletCollision/BroadphaseCollision/btBroadphaseProxy.h7
-rw-r--r--thirdparty/bullet/BulletCollision/BroadphaseCollision/btDbvt.h176
-rw-r--r--thirdparty/bullet/BulletCollision/BroadphaseCollision/btOverlappingPairCache.h2
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h8
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionDispatch/btCollisionWorldImporter.cpp4
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.cpp2
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.cpp6
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionDispatch/btInternalEdgeUtility.cpp93
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionDispatch/btInternalEdgeUtility.h3
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionDispatch/btSimulationIslandManager.cpp15
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionDispatch/btSimulationIslandManager.h4
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionShapes/btHeightfieldTerrainShape.cpp14
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionShapes/btHeightfieldTerrainShape.h39
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionShapes/btStridingMeshInterface.h2
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionShapes/btTriangleIndexVertexArray.h2
-rw-r--r--thirdparty/bullet/BulletCollision/Gimpact/btGImpactShape.h2
-rw-r--r--thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btComputeGjkEpaPenetration.h8
-rw-r--r--thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btGjkPairDetector.cpp40
-rw-r--r--thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btGjkPairDetector.h4
-rw-r--r--thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btManifoldPoint.h3
-rw-r--r--thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.cpp36
-rw-r--r--thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btMprPenetration.h10
-rw-r--r--thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btPersistentManifold.cpp5
-rw-r--r--thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btPersistentManifold.h7
-rw-r--r--thirdparty/bullet/BulletDynamics/ConstraintSolver/btBatchedConstraints.cpp2
-rw-r--r--thirdparty/bullet/BulletDynamics/ConstraintSolver/btContactSolverInfo.h16
-rw-r--r--thirdparty/bullet/BulletDynamics/ConstraintSolver/btGeneric6DofSpring2Constraint.cpp6
-rw-r--r--thirdparty/bullet/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.cpp851
-rw-r--r--thirdparty/bullet/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.h124
-rw-r--r--thirdparty/bullet/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.cpp4
-rw-r--r--thirdparty/bullet/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h18
-rw-r--r--thirdparty/bullet/BulletDynamics/Dynamics/btDynamicsWorld.h3
-rw-r--r--thirdparty/bullet/BulletDynamics/Dynamics/btRigidBody.cpp8
-rw-r--r--thirdparty/bullet/BulletDynamics/Dynamics/btRigidBody.h45
-rw-r--r--thirdparty/bullet/BulletDynamics/Featherstone/btMultiBody.cpp231
-rw-r--r--thirdparty/bullet/BulletDynamics/Featherstone/btMultiBody.h28
-rw-r--r--thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyConstraint.cpp34
-rw-r--r--thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyConstraintSolver.cpp184
-rw-r--r--thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyConstraintSolver.h7
-rw-r--r--thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyDynamicsWorld.cpp953
-rw-r--r--thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyDynamicsWorld.h17
-rw-r--r--thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyInplaceSolverIslandCallback.h247
-rw-r--r--thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyLink.h83
-rw-r--r--thirdparty/bullet/BulletDynamics/MLCPSolvers/btLemkeSolver.h2
-rw-r--r--thirdparty/bullet/BulletSoftBody/DeformableBodyInplaceSolverIslandCallback.h46
-rw-r--r--thirdparty/bullet/BulletSoftBody/btCGProjection.h106
-rw-r--r--thirdparty/bullet/BulletSoftBody/btConjugateGradient.h158
-rw-r--r--thirdparty/bullet/BulletSoftBody/btDefaultSoftBodySolver.cpp4
-rw-r--r--thirdparty/bullet/BulletSoftBody/btDefaultSoftBodySolver.h4
-rw-r--r--thirdparty/bullet/BulletSoftBody/btDeformableBackwardEulerObjective.cpp197
-rw-r--r--thirdparty/bullet/BulletSoftBody/btDeformableBackwardEulerObjective.h134
-rw-r--r--thirdparty/bullet/BulletSoftBody/btDeformableBodySolver.cpp485
-rw-r--r--thirdparty/bullet/BulletSoftBody/btDeformableBodySolver.h164
-rw-r--r--thirdparty/bullet/BulletSoftBody/btDeformableContactConstraint.cpp591
-rw-r--r--thirdparty/bullet/BulletSoftBody/btDeformableContactConstraint.h302
-rw-r--r--thirdparty/bullet/BulletSoftBody/btDeformableContactProjection.cpp509
-rw-r--r--thirdparty/bullet/BulletSoftBody/btDeformableContactProjection.h90
-rw-r--r--thirdparty/bullet/BulletSoftBody/btDeformableCorotatedForce.h125
-rw-r--r--thirdparty/bullet/BulletSoftBody/btDeformableGravityForce.h105
-rw-r--r--thirdparty/bullet/BulletSoftBody/btDeformableLagrangianForce.h364
-rw-r--r--thirdparty/bullet/BulletSoftBody/btDeformableLinearElasticityForce.h340
-rw-r--r--thirdparty/bullet/BulletSoftBody/btDeformableMassSpringForce.h255
-rw-r--r--thirdparty/bullet/BulletSoftBody/btDeformableMultiBodyConstraintSolver.cpp143
-rw-r--r--thirdparty/bullet/BulletSoftBody/btDeformableMultiBodyConstraintSolver.h61
-rw-r--r--thirdparty/bullet/BulletSoftBody/btDeformableMultiBodyDynamicsWorld.cpp653
-rw-r--r--thirdparty/bullet/BulletSoftBody/btDeformableMultiBodyDynamicsWorld.h165
-rw-r--r--thirdparty/bullet/BulletSoftBody/btDeformableNeoHookeanForce.h375
-rw-r--r--thirdparty/bullet/BulletSoftBody/btPreconditioner.h79
-rw-r--r--thirdparty/bullet/BulletSoftBody/btSoftBody.cpp872
-rw-r--r--thirdparty/bullet/BulletSoftBody/btSoftBody.h153
-rw-r--r--thirdparty/bullet/BulletSoftBody/btSoftBodyHelpers.cpp323
-rw-r--r--thirdparty/bullet/BulletSoftBody/btSoftBodyHelpers.h16
-rw-r--r--thirdparty/bullet/BulletSoftBody/btSoftBodyInternals.h545
-rw-r--r--thirdparty/bullet/BulletSoftBody/btSoftBodySolvers.h7
-rw-r--r--thirdparty/bullet/BulletSoftBody/btSparseSDF.h81
-rw-r--r--thirdparty/bullet/LinearMath/btImplicitQRSVD.h916
-rw-r--r--thirdparty/bullet/LinearMath/btMatrix3x3.h7
-rw-r--r--thirdparty/bullet/LinearMath/btMatrixX.h19
-rw-r--r--thirdparty/bullet/LinearMath/btScalar.h26
-rw-r--r--thirdparty/bullet/LinearMath/btSerializer.cpp1198
-rw-r--r--thirdparty/bullet/LinearMath/btSerializer.h2
-rw-r--r--thirdparty/bullet/LinearMath/btSerializer64.cpp1197
-rw-r--r--thirdparty/enet/LICENSE2
-rw-r--r--thirdparty/enet/enet/enet.h13
-rw-r--r--thirdparty/enet/patches/ipv6_support.patch105
-rw-r--r--thirdparty/enet/protocol.c19
-rw-r--r--thirdparty/libwebp/src/dec/frame_dec.c2
-rw-r--r--thirdparty/libwebp/src/dec/idec_dec.c11
-rw-r--r--thirdparty/libwebp/src/dec/vp8i_dec.h4
-rw-r--r--thirdparty/libwebp/src/dec/vp8l_dec.c10
-rw-r--r--thirdparty/libwebp/src/dec/vp8li_dec.h20
-rw-r--r--thirdparty/libwebp/src/demux/demux.c4
-rw-r--r--thirdparty/libwebp/src/dsp/dec_neon.c9
-rw-r--r--thirdparty/libwebp/src/dsp/dsp.h4
-rw-r--r--thirdparty/libwebp/src/dsp/lossless.c11
-rw-r--r--thirdparty/libwebp/src/dsp/lossless_common.h2
-rw-r--r--thirdparty/libwebp/src/dsp/lossless_enc_sse2.c3
-rw-r--r--thirdparty/libwebp/src/dsp/lossless_sse2.c3
-rw-r--r--thirdparty/libwebp/src/dsp/upsampling_msa.c4
-rw-r--r--thirdparty/libwebp/src/dsp/upsampling_neon.c14
-rw-r--r--thirdparty/libwebp/src/enc/histogram_enc.c2
-rw-r--r--thirdparty/libwebp/src/enc/picture_csp_enc.c18
-rw-r--r--thirdparty/libwebp/src/enc/vp8i_enc.h6
-rw-r--r--thirdparty/libwebp/src/mux/muxi.h4
-rw-r--r--thirdparty/libwebp/src/mux/muxread.c2
-rw-r--r--thirdparty/libwebp/src/utils/color_cache_utils.h2
-rw-r--r--thirdparty/libwebp/src/utils/thread_utils.c2
-rw-r--r--thirdparty/libwebp/src/utils/utils.c9
-rw-r--r--thirdparty/libwebp/src/webp/decode.h5
-rw-r--r--thirdparty/libwebp/src/webp/encode.h9
-rw-r--r--thirdparty/libwebp/src/webp/mux.h12
-rw-r--r--thirdparty/libwebp/src/webp/mux_types.h10
-rw-r--r--thirdparty/libwebp/src/webp/types.h18
-rw-r--r--thirdparty/xatlas/LICENSE27
-rw-r--r--thirdparty/xatlas/xatlas.cpp3806
-rw-r--r--thirdparty/xatlas/xatlas.h11
-rw-r--r--version.py1
531 files changed, 21945 insertions, 8202 deletions
diff --git a/.appveyor.yml b/.appveyor.yml
index b04e7d9ce8..05e7094981 100644
--- a/.appveyor.yml
+++ b/.appveyor.yml
@@ -1,16 +1,16 @@
-os: Visual Studio 2015
+image: Visual Studio 2019
+
+platform: x64
environment:
HOME: "%HOMEDRIVE%%HOMEPATH%"
- PYTHON: C:\Python27
+ PYTHON: C:\Python38
SCONS_CACHE_ROOT: "%HOME%\\scons_cache"
SCONS_CACHE_LIMIT: 1024
matrix:
- - VS: C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat
- GD_PLATFORM: windows
+ - GD_PLATFORM: windows
TOOLS: yes
TARGET: release_debug
- ARCH: amd64
init:
- ps: if ($env:APPVEYOR_REPO_BRANCH -ne "master") { $env:APPVEYOR_CACHE_SKIP_SAVE = "true" }
@@ -20,15 +20,12 @@ cache:
install:
- SET "PATH=%PYTHON%;%PYTHON%\\Scripts;%PATH%"
- - pip install -U wheel # needed for pip install scons to work, otherwise a flag is missing
- - pip install scons==3.0.1
- - if defined VS call "%VS%" %ARCH% # if defined - so we can also use mingw
+ - pip install scons==3.1.2
before_build:
- echo %GD_PLATFORM%
- python --version
- scons --version
- - cl.exe
- set "SCONS_CACHE=%SCONS_CACHE_ROOT%\%APPVEYOR_REPO_BRANCH%"
build_script:
diff --git a/.travis.yml b/.travis.yml
index 7350849d6a..c8b123c79c 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -94,7 +94,7 @@ matrix:
- name: Linux export template (release_debug, GCC 5, without 3D support)
stage: build
- env: PLATFORM=x11 TOOLS=no TARGET=release_debug CACHE_NAME=${PLATFORM}-gcc-5 EXTRA_ARGS="disable_3d=yes"
+ env: PLATFORM=x11 TOOLS=no TARGET=release_debug CACHE_NAME=${PLATFORM}-gcc-5 EXTRA_ARGS="CXXFLAGS=-fno-strict-aliasing disable_3d=yes"
os: linux
compiler: gcc
addons:
diff --git a/core/bind/core_bind.cpp b/core/bind/core_bind.cpp
index 3b189be4ab..68650019a2 100644
--- a/core/bind/core_bind.cpp
+++ b/core/bind/core_bind.cpp
@@ -400,6 +400,10 @@ bool _OS::is_window_always_on_top() const {
return OS::get_singleton()->is_window_always_on_top();
}
+bool _OS::is_window_focused() const {
+ return OS::get_singleton()->is_window_focused();
+}
+
void _OS::set_borderless_window(bool p_borderless) {
OS::get_singleton()->set_borderless_window(p_borderless);
}
@@ -1226,6 +1230,7 @@ void _OS::_bind_methods() {
ClassDB::bind_method(D_METHOD("is_window_maximized"), &_OS::is_window_maximized);
ClassDB::bind_method(D_METHOD("set_window_always_on_top", "enabled"), &_OS::set_window_always_on_top);
ClassDB::bind_method(D_METHOD("is_window_always_on_top"), &_OS::is_window_always_on_top);
+ ClassDB::bind_method(D_METHOD("is_window_focused"), &_OS::is_window_focused);
ClassDB::bind_method(D_METHOD("request_attention"), &_OS::request_attention);
ClassDB::bind_method(D_METHOD("get_real_window_size"), &_OS::get_real_window_size);
ClassDB::bind_method(D_METHOD("center_window"), &_OS::center_window);
@@ -3019,6 +3024,16 @@ float _Engine::get_frames_per_second() const {
return Engine::get_singleton()->get_frames_per_second();
}
+uint64_t _Engine::get_physics_frames() const {
+
+ return Engine::get_singleton()->get_physics_frames();
+}
+
+uint64_t _Engine::get_idle_frames() const {
+
+ return Engine::get_singleton()->get_idle_frames();
+}
+
void _Engine::set_time_scale(float p_scale) {
Engine::get_singleton()->set_time_scale(p_scale);
}
@@ -3103,6 +3118,8 @@ void _Engine::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_frames_drawn"), &_Engine::get_frames_drawn);
ClassDB::bind_method(D_METHOD("get_frames_per_second"), &_Engine::get_frames_per_second);
+ ClassDB::bind_method(D_METHOD("get_physics_frames"), &_Engine::get_physics_frames);
+ ClassDB::bind_method(D_METHOD("get_idle_frames"), &_Engine::get_idle_frames);
ClassDB::bind_method(D_METHOD("get_main_loop"), &_Engine::get_main_loop);
diff --git a/core/bind/core_bind.h b/core/bind/core_bind.h
index 46a5fdb5a4..65f20c375e 100644
--- a/core/bind/core_bind.h
+++ b/core/bind/core_bind.h
@@ -198,6 +198,7 @@ public:
virtual bool is_window_maximized() const;
virtual void set_window_always_on_top(bool p_enabled);
virtual bool is_window_always_on_top() const;
+ virtual bool is_window_focused() const;
virtual void request_attention();
virtual void center_window();
virtual void move_window_to_foreground();
@@ -746,6 +747,8 @@ public:
int get_target_fps() const;
float get_frames_per_second() const;
+ uint64_t get_physics_frames() const;
+ uint64_t get_idle_frames() const;
int get_frames_drawn();
diff --git a/core/class_db.cpp b/core/class_db.cpp
index 3cd04c6573..65f0c6008c 100644
--- a/core/class_db.cpp
+++ b/core/class_db.cpp
@@ -389,6 +389,13 @@ uint64_t ClassDB::get_api_hash(APIType p_api) {
while ((k = t->method_map.next(k))) {
+ String name = k->operator String();
+
+ ERR_CONTINUE(name.empty());
+
+ if (name[0] == '_')
+ continue; // Ignore non-virtual methods that start with an underscore
+
snames.push_back(*k);
}
diff --git a/core/engine.cpp b/core/engine.cpp
index e461bfe44a..1772cc7c48 100644
--- a/core/engine.cpp
+++ b/core/engine.cpp
@@ -94,11 +94,7 @@ Dictionary Engine::get_version_info() const {
Dictionary dict;
dict["major"] = VERSION_MAJOR;
dict["minor"] = VERSION_MINOR;
-#ifdef VERSION_PATCH
dict["patch"] = VERSION_PATCH;
-#else
- dict["patch"] = 0;
-#endif
dict["hex"] = VERSION_HEX;
dict["status"] = VERSION_STATUS;
dict["build"] = VERSION_BUILD;
diff --git a/core/io/file_access_pack.cpp b/core/io/file_access_pack.cpp
index bef92b938b..83ce03418a 100644
--- a/core/io/file_access_pack.cpp
+++ b/core/io/file_access_pack.cpp
@@ -34,8 +34,6 @@
#include <stdio.h>
-#define PACK_VERSION 1
-
Error PackedData::add_pack(const String &p_path, bool p_replace_files) {
for (int i = 0; i < sources.size(); i++) {
@@ -140,16 +138,14 @@ bool PackedSourcePCK::try_open_pack(const String &p_path, bool p_replace_files)
if (!f)
return false;
- //printf("try open %ls!\n", p_path.c_str());
-
uint32_t magic = f->get_32();
- if (magic != 0x43504447) {
+ if (magic != PACK_HEADER_MAGIC) {
//maybe at the end.... self contained exe
f->seek_end();
f->seek(f->get_position() - 4);
magic = f->get_32();
- if (magic != 0x43504447) {
+ if (magic != PACK_HEADER_MAGIC) {
f->close();
memdelete(f);
@@ -161,7 +157,7 @@ bool PackedSourcePCK::try_open_pack(const String &p_path, bool p_replace_files)
f->seek(f->get_position() - ds - 8);
magic = f->get_32();
- if (magic != 0x43504447) {
+ if (magic != PACK_HEADER_MAGIC) {
f->close();
memdelete(f);
@@ -172,9 +168,9 @@ bool PackedSourcePCK::try_open_pack(const String &p_path, bool p_replace_files)
uint32_t version = f->get_32();
uint32_t ver_major = f->get_32();
uint32_t ver_minor = f->get_32();
- f->get_32(); // ver_rev
+ f->get_32(); // patch number, not used for validation.
- if (version != PACK_VERSION) {
+ if (version != PACK_FORMAT_VERSION) {
f->close();
memdelete(f);
ERR_FAIL_V_MSG(false, "Pack version unsupported: " + itos(version) + ".");
diff --git a/core/io/file_access_pack.h b/core/io/file_access_pack.h
index 6ced2b2d4d..b6ea9c158f 100644
--- a/core/io/file_access_pack.h
+++ b/core/io/file_access_pack.h
@@ -37,6 +37,11 @@
#include "core/os/file_access.h"
#include "core/print_string.h"
+// Godot's packed file magic header ("GDPC" in ASCII).
+#define PACK_HEADER_MAGIC 0x43504447
+// The current packed file format version number.
+#define PACK_FORMAT_VERSION 1
+
class PackSource;
class PackedData {
diff --git a/core/io/marshalls.cpp b/core/io/marshalls.cpp
index 8c8f65c3a0..e847a9cf0c 100644
--- a/core/io/marshalls.cpp
+++ b/core/io/marshalls.cpp
@@ -803,6 +803,18 @@ Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bo
}
} break;
case Variant::OBJECT: {
+#ifdef DEBUG_ENABLED
+ // Test for potential wrong values sent by the debugger when it breaks.
+ Object *obj = p_variant;
+ if (!obj || !ObjectDB::instance_validate(obj)) {
+ // Object is invalid, send a NULL instead.
+ if (buf) {
+ encode_uint32(Variant::NIL, buf);
+ }
+ r_len += 4;
+ return OK;
+ }
+#endif // DEBUG_ENABLED
if (!p_full_objects) {
flags |= ENCODE_FLAG_OBJECT_AS_ID;
}
diff --git a/core/io/pck_packer.cpp b/core/io/pck_packer.cpp
index c317125c28..8bc73103e9 100644
--- a/core/io/pck_packer.cpp
+++ b/core/io/pck_packer.cpp
@@ -30,6 +30,7 @@
#include "pck_packer.h"
+#include "core/io/file_access_pack.h" // PACK_HEADER_MAGIC, PACK_FORMAT_VERSION
#include "core/os/file_access.h"
#include "core/version.h"
@@ -68,11 +69,11 @@ Error PCKPacker::pck_start(const String &p_file, int p_alignment) {
alignment = p_alignment;
- file->store_32(0x43504447); // MAGIC
- file->store_32(1); // # version
- file->store_32(VERSION_MAJOR); // # major
- file->store_32(VERSION_MINOR); // # minor
- file->store_32(0); // # revision
+ file->store_32(PACK_HEADER_MAGIC);
+ file->store_32(PACK_FORMAT_VERSION);
+ file->store_32(VERSION_MAJOR);
+ file->store_32(VERSION_MINOR);
+ file->store_32(VERSION_PATCH);
for (int i = 0; i < 16; i++) {
diff --git a/core/io/resource_loader.cpp b/core/io/resource_loader.cpp
index 5d85634895..7471ab4241 100644
--- a/core/io/resource_loader.cpp
+++ b/core/io/resource_loader.cpp
@@ -277,6 +277,11 @@ RES ResourceLoader::_load(const String &p_path, const String &p_original_path, c
ERR_FAIL_COND_V_MSG(found, RES(), "Failed loading resource: " + p_path + ".");
+#ifdef TOOLS_ENABLED
+ FileAccessRef file_check = FileAccess::create(FileAccess::ACCESS_RESOURCES);
+ ERR_FAIL_COND_V_MSG(!file_check->file_exists(p_path), RES(), "Resource file not found: " + p_path + ".");
+#endif
+
ERR_FAIL_V_MSG(RES(), "No loader found for resource: " + p_path + ".");
}
diff --git a/core/object.cpp b/core/object.cpp
index 35ccc38d4e..21666a334c 100644
--- a/core/object.cpp
+++ b/core/object.cpp
@@ -1185,13 +1185,11 @@ Error Object::emit_signal(const StringName &p_name, const Variant **p_args, int
const Connection &c = slot_map.getv(i).conn;
- Object *target;
-#ifdef DEBUG_ENABLED
- target = ObjectDB::get_instance(slot_map.getk(i)._id);
- ERR_CONTINUE(!target);
-#else
- target = c.target;
-#endif
+ Object *target = ObjectDB::get_instance(slot_map.getk(i)._id);
+ if (!target) {
+ // Target might have been deleted during signal callback, this is expected and OK.
+ continue;
+ }
const Variant **args = p_args;
int argc = p_argcount;
@@ -1519,10 +1517,6 @@ void Object::_disconnect(const StringName &p_signal, Object *p_to_object, const
Signal *s = signal_map.getptr(p_signal);
ERR_FAIL_COND_MSG(!s, vformat("Nonexistent signal '%s' in %s.", p_signal, to_string()));
- ERR_FAIL_COND_MSG(s->lock > 0,
- vformat("Attempt to disconnect %s signal '%s' while in emission callback '%s' (in target %s). Use CONNECT_DEFERRED (to be able to safely disconnect) or CONNECT_ONESHOT (for automatic disconnection) as connection flags.",
- to_string(), p_signal, p_to_method, p_to_object->to_string()));
-
Signal::Target target(p_to_object->get_instance_id(), p_to_method);
ERR_FAIL_COND_MSG(!s->slot_map.has(target), "Disconnecting nonexistent signal '" + p_signal + "', slot: " + itos(target._id) + ":" + target.method + ".");
diff --git a/core/os/os.cpp b/core/os/os.cpp
index edb2416b67..81dea159a6 100644
--- a/core/os/os.cpp
+++ b/core/os/os.cpp
@@ -343,6 +343,12 @@ String OS::get_cache_path() const {
return ".";
}
+// Path to macOS .app bundle resources
+String OS::get_bundle_resource_dir() const {
+
+ return ".";
+};
+
// OS specific path for user://
String OS::get_user_data_dir() const {
diff --git a/core/os/os.h b/core/os/os.h
index cdc9536653..714c4e3f09 100644
--- a/core/os/os.h
+++ b/core/os/os.h
@@ -222,6 +222,7 @@ public:
virtual bool is_window_maximized() const { return true; }
virtual void set_window_always_on_top(bool p_enabled) {}
virtual bool is_window_always_on_top() const { return false; }
+ virtual bool is_window_focused() const { return true; }
virtual void set_console_visible(bool p_enabled) {}
virtual bool is_console_visible() const { return false; }
virtual void request_attention() {}
@@ -410,6 +411,7 @@ public:
virtual String get_data_path() const;
virtual String get_config_path() const;
virtual String get_cache_path() const;
+ virtual String get_bundle_resource_dir() const;
virtual String get_user_data_dir() const;
virtual String get_resource_dir() const;
diff --git a/core/project_settings.cpp b/core/project_settings.cpp
index a30967dcca..a01a8a35c6 100644
--- a/core/project_settings.cpp
+++ b/core/project_settings.cpp
@@ -383,8 +383,16 @@ Error ProjectSettings::_setup(const String &p_path, const String &p_main_pack, b
}
}
- // Attempt with PCK bundled into executable
+#ifdef OSX_ENABLED
+ // Attempt to load PCK from macOS .app bundle resources
+ if (!found) {
+ if (_load_resource_pack(OS::get_singleton()->get_bundle_resource_dir().plus_file(exec_basename + ".pck"))) {
+ found = true;
+ }
+ }
+#endif
+ // Attempt with PCK bundled into executable
if (!found) {
if (_load_resource_pack(exec_path)) {
found = true;
diff --git a/core/resource.cpp b/core/resource.cpp
index 1c9d3f8d49..30e09716aa 100644
--- a/core/resource.cpp
+++ b/core/resource.cpp
@@ -68,7 +68,10 @@ void Resource::set_path(const String &p_path, bool p_take_over) {
if (p_take_over) {
ResourceCache::lock->write_lock();
- ResourceCache::resources.get(p_path)->set_name("");
+ Resource **res = ResourceCache::resources.getptr(p_path);
+ if (res) {
+ (*res)->set_name("");
+ }
ResourceCache::lock->write_unlock();
} else {
ResourceCache::lock->read_lock();
diff --git a/core/version.h b/core/version.h
index a790152ca4..42c85c1b13 100644
--- a/core/version.h
+++ b/core/version.h
@@ -28,6 +28,9 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
+#ifndef GODOT_VERSION_H
+#define GODOT_VERSION_H
+
#include "core/version_generated.gen.h"
// Godot versions are of the form <major>.<minor> for the initial release,
@@ -38,18 +41,18 @@
// forward-compatible.
// Example: "3.1"
#define VERSION_BRANCH "" _MKSTR(VERSION_MAJOR) "." _MKSTR(VERSION_MINOR)
-#ifdef VERSION_PATCH
+#if VERSION_PATCH
// Example: "3.1.4"
#define VERSION_NUMBER "" VERSION_BRANCH "." _MKSTR(VERSION_PATCH)
+#else // patch is 0, we don't include it in the "pretty" version number.
+// Example: "3.1" instead of "3.1.0"
+#define VERSION_NUMBER "" VERSION_BRANCH
+#endif // VERSION_PATCH
+
// Version number encoded as hexadecimal int with one byte for each number,
// for easy comparison from code.
// Example: 3.1.4 will be 0x030104, making comparison easy from script.
#define VERSION_HEX 0x10000 * VERSION_MAJOR + 0x100 * VERSION_MINOR + VERSION_PATCH
-#else
-// Example: "3.1"
-#define VERSION_NUMBER "" VERSION_BRANCH
-#define VERSION_HEX 0x10000 * VERSION_MAJOR + 0x100 * VERSION_MINOR
-#endif // VERSION_PATCH
// Describes the full configuration of that Godot version, including the version number,
// the status (beta, stable, etc.) and potential module-specific features (e.g. mono).
@@ -64,3 +67,5 @@
// Same as above, but prepended with Godot's name and a cosmetic "v" for "version".
// Example: "Godot v3.1.4.stable.official.mono"
#define VERSION_FULL_NAME "" VERSION_NAME " v" VERSION_FULL_BUILD
+
+#endif // GODOT_VERSION_H
diff --git a/doc/classes/Array.xml b/doc/classes/Array.xml
index 2d330fc935..c192cee1fe 100644
--- a/doc/classes/Array.xml
+++ b/doc/classes/Array.xml
@@ -331,17 +331,18 @@
<argument index="1" name="func" type="String">
</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 [code]true[/code] if the first argument is less than the second, and return [code]false[/code] otherwise.
+ 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].
[b]Note:[/b] you cannot randomize the return value as the heapsort algorithm expects a deterministic result. Doing so will result in unexpected behavior.
[codeblock]
class MyCustomSorter:
- static func sort(a, b):
+ static func sort_ascending(a, b):
if a[0] &lt; b[0]:
return true
return false
var my_items = [[5, "Potato"], [9, "Rice"], [4, "Tomato"]]
- my_items.sort_custom(MyCustomSorter, "sort")
+ my_items.sort_custom(MyCustomSorter, "sort_ascending")
+ print(my_items) # Prints [[4, Tomato], [5, Potato], [9, Rice]]
[/codeblock]
</description>
</method>
diff --git a/doc/classes/ArrayMesh.xml b/doc/classes/ArrayMesh.xml
index 62ff0edbd2..e3e9c38419 100644
--- a/doc/classes/ArrayMesh.xml
+++ b/doc/classes/ArrayMesh.xml
@@ -23,6 +23,7 @@
The [code]MeshInstance[/code] is ready to be added to the SceneTree to be shown.
</description>
<tutorials>
+ <link>http://docs.godotengine.org/en/latest/tutorials/content/procedural_geometry/arraymesh.html</link>
</tutorials>
<methods>
<method name="add_blend_shape">
@@ -185,6 +186,7 @@
</methods>
<members>
<member name="blend_shape_mode" type="int" setter="set_blend_shape_mode" getter="get_blend_shape_mode" enum="Mesh.BlendShapeMode" default="1">
+ Sets the blend shape mode to one of [enum Mesh.BlendShapeMode].
</member>
<member name="custom_aabb" type="AABB" setter="set_custom_aabb" getter="get_custom_aabb" default="AABB( 0, 0, 0, 0, 0, 0 )">
Overrides the [AABB] with one defined by user for use with frustum culling. Especially useful to avoid unexpected culling when using a shader to offset vertices.
diff --git a/doc/classes/AudioStreamPlayer.xml b/doc/classes/AudioStreamPlayer.xml
index 89fc18476b..0eadf27c4d 100644
--- a/doc/classes/AudioStreamPlayer.xml
+++ b/doc/classes/AudioStreamPlayer.xml
@@ -21,6 +21,7 @@
<return type="AudioStreamPlayback">
</return>
<description>
+ Returns the [AudioStreamPlayback] object associated with this [AudioStreamPlayer].
</description>
</method>
<method name="play">
@@ -69,6 +70,7 @@
The [AudioStream] object to be played.
</member>
<member name="stream_paused" type="bool" setter="set_stream_paused" getter="get_stream_paused" default="false">
+ If [code]true[/code], the playback is paused. You can resume it by setting [code]stream_paused[/code] to [code]false[/code].
</member>
<member name="volume_db" type="float" setter="set_volume_db" getter="get_volume_db" default="0.0">
Volume of sound, in dB.
diff --git a/doc/classes/AudioStreamPlayer2D.xml b/doc/classes/AudioStreamPlayer2D.xml
index 4734aff770..ec3b7872b7 100644
--- a/doc/classes/AudioStreamPlayer2D.xml
+++ b/doc/classes/AudioStreamPlayer2D.xml
@@ -21,6 +21,7 @@
<return type="AudioStreamPlayback">
</return>
<description>
+ Returns the [AudioStreamPlayback] object associated with this [AudioStreamPlayer2D].
</description>
</method>
<method name="play">
@@ -75,6 +76,7 @@
The [AudioStream] object to be played.
</member>
<member name="stream_paused" type="bool" setter="set_stream_paused" getter="get_stream_paused" default="false">
+ If [code]true[/code], the playback is paused. You can resume it by setting [code]stream_paused[/code] to [code]false[/code].
</member>
<member name="volume_db" type="float" setter="set_volume_db" getter="get_volume_db" default="0.0">
Base volume without dampening.
diff --git a/doc/classes/AudioStreamPlayer3D.xml b/doc/classes/AudioStreamPlayer3D.xml
index a73f96d082..5e12e06650 100644
--- a/doc/classes/AudioStreamPlayer3D.xml
+++ b/doc/classes/AudioStreamPlayer3D.xml
@@ -21,6 +21,7 @@
<return type="AudioStreamPlayback">
</return>
<description>
+ Returns the [AudioStreamPlayback] object associated with this [AudioStreamPlayer3D].
</description>
</method>
<method name="play">
@@ -99,6 +100,7 @@
The [AudioStream] object to be played.
</member>
<member name="stream_paused" type="bool" setter="set_stream_paused" getter="get_stream_paused" default="false">
+ If [code]true[/code], the playback is paused. You can resume it by setting [code]stream_paused[/code] to [code]false[/code].
</member>
<member name="unit_db" type="float" setter="set_unit_db" getter="get_unit_db" default="0.0">
Base sound level unaffected by dampening, in dB.
diff --git a/doc/classes/BaseButton.xml b/doc/classes/BaseButton.xml
index 21f46efe84..0128e7b220 100644
--- a/doc/classes/BaseButton.xml
+++ b/doc/classes/BaseButton.xml
@@ -112,6 +112,7 @@
The state of buttons are disabled.
</constant>
<constant name="DRAW_HOVER_PRESSED" value="4" enum="DrawMode">
+ The state of buttons are both hovered and pressed.
</constant>
<constant name="ACTION_MODE_BUTTON_PRESS" value="0" enum="ActionMode">
Require just a press to consider the button clicked.
diff --git a/doc/classes/CPUParticles.xml b/doc/classes/CPUParticles.xml
index e68b0feb2d..cef0ee7587 100644
--- a/doc/classes/CPUParticles.xml
+++ b/doc/classes/CPUParticles.xml
@@ -367,5 +367,8 @@
<constant name="EMISSION_SHAPE_DIRECTED_POINTS" value="4" enum="EmissionShape">
Particles will be emitted at a position chosen randomly among [member emission_points]. Particle velocity and rotation will be set based on [member emission_normals]. Particle color will be modulated by [member emission_colors].
</constant>
+ <constant name="EMISSION_SHAPE_MAX" value="5" enum="EmissionShape">
+ Represents the size of the [enum EmissionShape] enum.
+ </constant>
</constants>
</class>
diff --git a/doc/classes/CPUParticles2D.xml b/doc/classes/CPUParticles2D.xml
index c8dbffb4cb..dac00051a9 100644
--- a/doc/classes/CPUParticles2D.xml
+++ b/doc/classes/CPUParticles2D.xml
@@ -360,5 +360,8 @@
<constant name="EMISSION_SHAPE_DIRECTED_POINTS" value="4" enum="EmissionShape">
Particles will be emitted at a position chosen randomly among [member emission_points]. Particle velocity and rotation will be set based on [member emission_normals]. Particle color will be modulated by [member emission_colors].
</constant>
+ <constant name="EMISSION_SHAPE_MAX" value="5" enum="EmissionShape">
+ Represents the size of the [enum EmissionShape] enum.
+ </constant>
</constants>
</class>
diff --git a/doc/classes/CanvasItem.xml b/doc/classes/CanvasItem.xml
index 8372d15324..54d917c931 100644
--- a/doc/classes/CanvasItem.xml
+++ b/doc/classes/CanvasItem.xml
@@ -42,6 +42,7 @@
<argument index="7" name="antialiased" type="bool" default="false">
</argument>
<description>
+ Draws an arc between the given angles. The larger the value of [code]point_count[/code], the smoother the curve.
</description>
</method>
<method name="draw_char">
diff --git a/doc/classes/CollisionObject2D.xml b/doc/classes/CollisionObject2D.xml
index b9ec9480cf..bbc2e44dc0 100644
--- a/doc/classes/CollisionObject2D.xml
+++ b/doc/classes/CollisionObject2D.xml
@@ -44,6 +44,7 @@
<argument index="0" name="owner_id" type="int">
</argument>
<description>
+ Returns the [code]one_way_collision_margin[/code] of the shape owner identified by given [code]owner_id[/code].
</description>
</method>
<method name="get_shape_owners">
@@ -199,6 +200,7 @@
<argument index="1" name="margin" type="float">
</argument>
<description>
+ Sets the [code]one_way_collision_margin[/code] of the shape owner identified by given [code]owner_id[/code] to [code]margin[/code] pixels.
</description>
</method>
<method name="shape_owner_set_transform">
diff --git a/doc/classes/ColorPickerButton.xml b/doc/classes/ColorPickerButton.xml
index e8c78fb6bf..37116b096a 100644
--- a/doc/classes/ColorPickerButton.xml
+++ b/doc/classes/ColorPickerButton.xml
@@ -43,10 +43,12 @@
</signal>
<signal name="picker_created">
<description>
+ Emitted when the [ColorPicker] is created (the button is pressed for the first time).
</description>
</signal>
<signal name="popup_closed">
<description>
+ Emitted when the [ColorPicker] is closed.
</description>
</signal>
</signals>
diff --git a/doc/classes/Control.xml b/doc/classes/Control.xml
index 75d5a72fb1..d309015453 100644
--- a/doc/classes/Control.xml
+++ b/doc/classes/Control.xml
@@ -504,7 +504,7 @@
<description>
Virtual method to be implemented by the user. Returns whether the given [code]point[/code] is inside this control.
If not overridden, default behavior is checking if the point is within control's Rect.
- [b]Node:[/b] If you want to check if a point is inside the control, you can use [code]get_rect().has_point(point)[/code].
+ [b]Note:[/b] If you want to check if a point is inside the control, you can use [code]get_rect().has_point(point)[/code].
</description>
</method>
<method name="has_shader_override" qualifiers="const">
diff --git a/doc/classes/Crypto.xml b/doc/classes/Crypto.xml
index bce7895973..bb2c443618 100644
--- a/doc/classes/Crypto.xml
+++ b/doc/classes/Crypto.xml
@@ -22,6 +22,7 @@
key.save("user://generated.key")
cert.save("user://generated.crt")
[/codeblock]
+ [b]Note:[/b] Not available in HTML5 exports.
</description>
<tutorials>
</tutorials>
diff --git a/doc/classes/CryptoKey.xml b/doc/classes/CryptoKey.xml
index 8c825c9e1c..8feb7d4809 100644
--- a/doc/classes/CryptoKey.xml
+++ b/doc/classes/CryptoKey.xml
@@ -6,6 +6,7 @@
<description>
The CryptoKey class represents a cryptographic key. Keys can be loaded and saved like any other [Resource].
They can be used to generate a self-signed [X509Certificate] via [method Crypto.generate_self_signed_certificate] and as private key in [method StreamPeerSSL.accept_stream] along with the appropriate certificate.
+ [b]Note:[/b] Not available in HTML5 exports.
</description>
<tutorials>
</tutorials>
diff --git a/doc/classes/Directory.xml b/doc/classes/Directory.xml
index 754fafadbe..91256359fb 100644
--- a/doc/classes/Directory.xml
+++ b/doc/classes/Directory.xml
@@ -5,6 +5,7 @@
</brief_description>
<description>
Directory type. It is used to manage directories and their content (not restricted to the project folder).
+ When creating a new [Directory], its default opened directory will be [code]res://[/code]. This may change in the future, so it is advised to always use [method open] to initialize your [Directory] where you want to operate, with explicit error checking.
Here is an example on how to iterate through the files of a directory:
[codeblock]
func dir_contents(path):
diff --git a/doc/classes/Engine.xml b/doc/classes/Engine.xml
index 187e13d7bd..53ddde0e4a 100644
--- a/doc/classes/Engine.xml
+++ b/doc/classes/Engine.xml
@@ -41,7 +41,7 @@
<return type="int">
</return>
<description>
- Returns the total number of frames drawn.
+ Returns the total number of frames drawn. If the render loop is disabled with [code]--disable-render-loop[/code] via command line, this returns [code]0[/code]. See also [method get_idle_frames].
</description>
</method>
<method name="get_frames_per_second" qualifiers="const">
@@ -51,6 +51,13 @@
Returns the frames per second of the running game.
</description>
</method>
+ <method name="get_idle_frames" qualifiers="const">
+ <return type="int">
+ </return>
+ <description>
+ Returns the total number of frames passed since engine initialization which is advanced on each [b]idle frame[/b], regardless of whether the render loop is enabled. See also [method get_frames_drawn].
+ </description>
+ </method>
<method name="get_license_info" qualifiers="const">
<return type="Dictionary">
</return>
@@ -72,6 +79,13 @@
Returns the main loop object (see [MainLoop] and [SceneTree]).
</description>
</method>
+ <method name="get_physics_frames" qualifiers="const">
+ <return type="int">
+ </return>
+ <description>
+ Returns the total number of frames passed since engine initialization which is advanced on each [b]physics frame[/b].
+ </description>
+ </method>
<method name="get_physics_interpolation_fraction" qualifiers="const">
<return type="float">
</return>
@@ -85,6 +99,7 @@
<argument index="0" name="name" type="String">
</argument>
<description>
+ Returns a global singleton with given [code]name[/code]. Often used for plugins, e.g. GodotPayments.
</description>
</method>
<method name="get_version_info" qualifiers="const">
@@ -116,6 +131,7 @@
<argument index="0" name="name" type="String">
</argument>
<description>
+ Returns [code]true[/code] if a singleton with given [code]name[/code] exists in global scope.
</description>
</method>
<method name="is_in_physics_frame" qualifiers="const">
@@ -134,6 +150,7 @@
The number of fixed iterations per second (for fixed process and physics).
</member>
<member name="physics_jitter_fix" type="float" setter="set_physics_jitter_fix" getter="get_physics_jitter_fix" default="0.5">
+ Controls how much physic 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.
</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 1feccec501..702ea0a999 100644
--- a/doc/classes/Environment.xml
+++ b/doc/classes/Environment.xml
@@ -21,6 +21,7 @@
<argument index="0" name="idx" type="int">
</argument>
<description>
+ Returns [code]true[/code] if the glow level [code]idx[/code] is specified, [code]false[/code] otherwise.
</description>
</method>
<method name="set_glow_level">
@@ -31,132 +32,133 @@
<argument index="1" name="enabled" type="bool">
</argument>
<description>
+ Enables or disables the glow level at index [code]idx[/code]. Each level relies on the previous level. This means that enabling higher glow levels will slow down the glow effect rendering, even if previous levels aren't enabled.
</description>
</method>
</methods>
<members>
<member name="adjustment_brightness" type="float" setter="set_adjustment_brightness" getter="get_adjustment_brightness" default="1.0">
- Global brightness value of the rendered scene (default value is 1).
+ The global brightness value of the rendered scene. Effective only if [code]adjustment_enabled[/code] is [code]true[/code].
</member>
<member name="adjustment_color_correction" type="Texture" setter="set_adjustment_color_correction" getter="get_adjustment_color_correction">
- Applies the provided [Texture] resource to affect the global color aspect of the rendered scene.
+ Applies the provided [Texture] resource to affect the global color aspect of the rendered scene. Effective only if [code]adjustment_enabled[/code] is [code]true[/code].
</member>
<member name="adjustment_contrast" type="float" setter="set_adjustment_contrast" getter="get_adjustment_contrast" default="1.0">
- Global contrast value of the rendered scene (default value is 1).
+ The global contrast value of the rendered scene (default value is 1). Effective only if [code]adjustment_enabled[/code] is [code]true[/code].
</member>
<member name="adjustment_enabled" type="bool" setter="set_adjustment_enable" getter="is_adjustment_enabled" default="false">
- Enables the [code]adjustment_*[/code] options provided by this resource. If [code]false[/code], adjustments modifications will have no effect on the rendered scene.
+ If [code]true[/code], enables the [code]adjustment_*[/code] properties provided by this resource. If [code]false[/code], modifications to the [code]adjustment_*[/code] properties will have no effect on the rendered scene.
</member>
<member name="adjustment_saturation" type="float" setter="set_adjustment_saturation" getter="get_adjustment_saturation" default="1.0">
- Global color saturation value of the rendered scene (default value is 1).
+ The global color saturation value of the rendered scene (default value is 1). Effective only if [code]adjustment_enabled[/code] is [code]true[/code].
</member>
<member name="ambient_light_color" type="Color" setter="set_ambient_light_color" getter="get_ambient_light_color" default="Color( 0, 0, 0, 1 )">
- [Color] of the ambient light.
+ The ambient light's [Color].
</member>
<member name="ambient_light_energy" type="float" setter="set_ambient_light_energy" getter="get_ambient_light_energy" default="1.0">
- Energy of the ambient light. The higher the value, the stronger the light.
+ The ambient light's energy. The higher the value, the stronger the light.
</member>
<member name="ambient_light_sky_contribution" type="float" setter="set_ambient_light_sky_contribution" getter="get_ambient_light_sky_contribution" default="1.0">
Defines the amount of light that the sky brings on the scene. A value of 0 means that the sky's light emission has no effect on the scene illumination, thus all ambient illumination is provided by the ambient light. On the contrary, a value of 1 means that all the light that affects the scene is provided by the sky, thus the ambient light parameter has no effect on the scene.
</member>
<member name="auto_exposure_enabled" type="bool" setter="set_tonemap_auto_exposure" getter="get_tonemap_auto_exposure" default="false">
- Enables the tonemapping auto exposure mode of the scene renderer. If activated, the renderer will automatically determine the exposure setting to adapt to the illumination of the scene and the observed light.
+ If [code]true[/code], enables the tonemapping auto exposure mode of the scene renderer. If [code]true[/code], the renderer will automatically determine the exposure setting to adapt to the scene's illumination and the observed light.
</member>
<member name="auto_exposure_max_luma" type="float" setter="set_tonemap_auto_exposure_max" getter="get_tonemap_auto_exposure_max" default="8.0">
- Maximum luminance value for the auto exposure.
+ The maximum luminance value for the auto exposure.
</member>
<member name="auto_exposure_min_luma" type="float" setter="set_tonemap_auto_exposure_min" getter="get_tonemap_auto_exposure_min" default="0.05">
- Minimum luminance value for the auto exposure.
+ The minimum luminance value for the auto exposure.
</member>
<member name="auto_exposure_scale" type="float" setter="set_tonemap_auto_exposure_grey" getter="get_tonemap_auto_exposure_grey" default="0.4">
- Scale of the auto exposure effect. Affects the intensity of auto exposure.
+ The scale of the auto exposure effect. Affects the intensity of auto exposure.
</member>
<member name="auto_exposure_speed" type="float" setter="set_tonemap_auto_exposure_speed" getter="get_tonemap_auto_exposure_speed" default="0.5">
- Speed of the auto exposure effect. Affects the time needed for the camera to perform auto exposure.
+ The speed of the auto exposure effect. Affects the time needed for the camera to perform auto exposure.
</member>
<member name="background_camera_feed_id" type="int" setter="set_camera_feed_id" getter="get_camera_feed_id" default="1">
- The id of the camera feed to show in the background.
+ The ID of the camera feed to show in the background.
</member>
<member name="background_canvas_max_layer" type="int" setter="set_canvas_max_layer" getter="get_canvas_max_layer" default="0">
- Maximum layer id (if using Layer background mode).
+ The maximum layer ID to display. Only effective when using the [constant BG_CANVAS] background mode.
</member>
<member name="background_color" type="Color" setter="set_bg_color" getter="get_bg_color" default="Color( 0, 0, 0, 1 )">
- Color displayed for clear areas of the scene (if using Custom color or Color+Sky background modes).
+ The [Color] displayed for clear areas of the scene. Only effective when using the [constant BG_COLOR] or [constant BG_COLOR_SKY] background modes).
</member>
<member name="background_energy" type="float" setter="set_bg_energy" getter="get_bg_energy" default="1.0">
- Power of light emitted by the background.
+ The power of the light emitted by the background.
</member>
<member name="background_mode" type="int" setter="set_background" getter="get_background" enum="Environment.BGMode" default="0">
- Defines the mode of background.
+ The background mode. See [enum BGMode] for possible values.
</member>
<member name="background_sky" type="Sky" setter="set_sky" getter="get_sky">
- [Sky] resource defined as background.
+ The [Sky] resource defined as background.
</member>
<member name="background_sky_custom_fov" type="float" setter="set_sky_custom_fov" getter="get_sky_custom_fov" default="0.0">
- [Sky] resource's custom field of view.
+ The [Sky] resource's custom field of view.
</member>
<member name="background_sky_orientation" type="Basis" setter="set_sky_orientation" getter="get_sky_orientation" default="Basis( 1, 0, 0, 0, 1, 0, 0, 0, 1 )">
- [Sky] resource's rotation expressed as a [Basis].
+ The [Sky] resource's rotation expressed as a [Basis].
</member>
<member name="background_sky_rotation" type="Vector3" setter="set_sky_rotation" getter="get_sky_rotation" default="Vector3( 0, 0, 0 )">
- [Sky] resource's rotation expressed as Euler angles in radians.
+ The [Sky] resource's rotation expressed as Euler angles in radians.
</member>
<member name="background_sky_rotation_degrees" type="Vector3" setter="set_sky_rotation_degrees" getter="get_sky_rotation_degrees" default="Vector3( 0, 0, 0 )">
- [Sky] resource's rotation expressed as Euler angles in degrees.
+ The [Sky] resource's rotation expressed as Euler angles in degrees.
</member>
<member name="dof_blur_far_amount" type="float" setter="set_dof_blur_far_amount" getter="get_dof_blur_far_amount" default="0.1">
- Amount of far blur.
+ The amount of far blur for the depth-of-field effect.
</member>
<member name="dof_blur_far_distance" type="float" setter="set_dof_blur_far_distance" getter="get_dof_blur_far_distance" default="10.0">
- Distance from the camera where the far blur effect affects the rendering.
+ The distance from the camera where the far blur effect affects the rendering.
</member>
<member name="dof_blur_far_enabled" type="bool" setter="set_dof_blur_far_enabled" getter="is_dof_blur_far_enabled" default="false">
- Enables the far blur effect.
+ If [code]true[/code], enables the depth-of-field far blur effect.
</member>
<member name="dof_blur_far_quality" type="int" setter="set_dof_blur_far_quality" getter="get_dof_blur_far_quality" enum="Environment.DOFBlurQuality" default="1">
- Quality of the far blur quality.
+ The depth-of-field far blur's quality. Higher values can mitigate the visible banding effect seen at higher strengths, but are much slower.
</member>
<member name="dof_blur_far_transition" type="float" setter="set_dof_blur_far_transition" getter="get_dof_blur_far_transition" default="5.0">
- Transition between no-blur area and far blur.
+ The length of the transition between the no-blur area and far blur.
</member>
<member name="dof_blur_near_amount" type="float" setter="set_dof_blur_near_amount" getter="get_dof_blur_near_amount" default="0.1">
- Amount of near blur.
+ The amount of near blur for the depth-of-field effect.
</member>
<member name="dof_blur_near_distance" type="float" setter="set_dof_blur_near_distance" getter="get_dof_blur_near_distance" default="2.0">
Distance from the camera where the near blur effect affects the rendering.
</member>
<member name="dof_blur_near_enabled" type="bool" setter="set_dof_blur_near_enabled" getter="is_dof_blur_near_enabled" default="false">
- Enables the near blur effect.
+ If [code]true[/code], enables the depth-of-field near blur effect.
</member>
<member name="dof_blur_near_quality" type="int" setter="set_dof_blur_near_quality" getter="get_dof_blur_near_quality" enum="Environment.DOFBlurQuality" default="1">
- Quality of the near blur quality.
+ The depth-of-field near blur's quality. Higher values can mitigate the visible banding effect seen at higher strengths, but are much slower.
</member>
<member name="dof_blur_near_transition" type="float" setter="set_dof_blur_near_transition" getter="get_dof_blur_near_transition" default="1.0">
- Transition between near blur and no-blur area.
+ The length of the transition between the near blur and no-blur area.
</member>
<member name="fog_color" type="Color" setter="set_fog_color" getter="get_fog_color" default="Color( 0.5, 0.6, 0.7, 1 )">
- Fog's [Color].
+ The fog's [Color].
</member>
<member name="fog_depth_begin" type="float" setter="set_fog_depth_begin" getter="get_fog_depth_begin" default="10.0">
- Fog's depth starting distance from the camera.
+ The fog's depth starting distance from the camera.
</member>
<member name="fog_depth_curve" type="float" setter="set_fog_depth_curve" getter="get_fog_depth_curve" default="1.0">
- Value defining the fog depth intensity.
+ The fog depth's intensity curve. A number of presets are available in the [b]Inspector[/b] by right-clicking the curve.
</member>
<member name="fog_depth_enabled" type="bool" setter="set_fog_depth_enabled" getter="is_fog_depth_enabled" default="true">
- Enables the fog depth.
+ If [code]true[/code], the depth fog effect is enabled. When enabled, fog will appear in the distance (relative to the camera).
</member>
<member name="fog_depth_end" type="float" setter="set_fog_depth_end" getter="get_fog_depth_end" default="100.0">
- Fog's depth end distance from the camera. If this value is set to 0, it will be equal to the current camera's [member Camera.far] value.
+ The fog's depth end distance from the camera. If this value is set to 0, it will be equal to the current camera's [member Camera.far] value.
</member>
<member name="fog_enabled" type="bool" setter="set_fog_enabled" getter="is_fog_enabled" default="false">
- Enables the fog. Needs [member fog_height_enabled] and/or [member fog_depth_enabled] to actually display fog.
+ If [code]true[/code], fog effects are enabled. [member fog_height_enabled] and/or [member fog_depth_enabled] must be set to [code]true[/code] to actually display fog.
</member>
<member name="fog_height_curve" type="float" setter="set_fog_height_curve" getter="get_fog_height_curve" default="1.0">
- Value defining the fog height intensity.
+ The height fog's intensity. A number of presets are available in the [b]Inspector[/b] by right-clicking the curve.
</member>
<member name="fog_height_enabled" type="bool" setter="set_fog_height_enabled" getter="is_fog_height_enabled" default="false">
- Enables the fog height.
+ If [code]true[/code], the height fog effect is enabled. When enabled, fog will appear in a defined height range, regardless of the distance from the camera. This can be used to simulate "deep water" effects with a lower performance cost compared to a dedicated shader.
</member>
<member name="fog_height_max" type="float" setter="set_fog_height_max" getter="get_fog_height_max" default="0.0">
The Y coordinate where the height fog will be the most intense. If this value is greater than [member fog_height_min], fog will be displayed from bottom to top. Otherwise, it will be displayed from top to bottom.
@@ -165,131 +167,151 @@
The Y coordinate where the height fog will be the least intense. If this value is greater than [member fog_height_max], fog will be displayed from top to bottom. Otherwise, it will be displayed from bottom to top.
</member>
<member name="fog_sun_amount" type="float" setter="set_fog_sun_amount" getter="get_fog_sun_amount" default="0.0">
- Amount of sun that affects the fog rendering.
+ The intensity of the depth fog color transition when looking towards the sun. The sun's direction is determined automatically using the DirectionalLight node in the scene.
</member>
<member name="fog_sun_color" type="Color" setter="set_fog_sun_color" getter="get_fog_sun_color" default="Color( 1, 0.9, 0.7, 1 )">
- Sun [Color].
+ The depth fog's [Color] when looking towards the sun.
</member>
<member name="fog_transmit_curve" type="float" setter="set_fog_transmit_curve" getter="get_fog_transmit_curve" default="1.0">
- Amount of light that the fog transmits.
+ The intensity of the fog light transmittance effect. Amount of light that the fog transmits.
</member>
<member name="fog_transmit_enabled" type="bool" setter="set_fog_transmit_enabled" getter="is_fog_transmit_enabled" default="false">
- Enables fog's light transmission. If enabled, lets reflections light to be transmitted by the fog.
+ Enables fog's light transmission effect. If [code]true[/code], light will be more visible in the fog to simulate light scattering as in real life.
</member>
<member name="glow_bicubic_upscale" type="bool" setter="set_glow_bicubic_upscale" getter="is_glow_bicubic_upscale_enabled" default="false">
- Smooths out blockiness created by sampling higher levels.
+ Smooths out the blockiness created by sampling higher levels, at the cost of performance.
+ [b]Note:[/b] When using the GLES2 renderer, this is only available if the GPU supports the [code]GL_EXT_gpu_shader4[/code] extension.
</member>
<member name="glow_blend_mode" type="int" setter="set_glow_blend_mode" getter="get_glow_blend_mode" enum="Environment.GlowBlendMode" default="2">
- Glow blending mode.
+ The glow blending mode.
</member>
<member name="glow_bloom" type="float" setter="set_glow_bloom" getter="get_glow_bloom" default="0.0">
- Bloom value (global glow).
+ The bloom's intensity. If set to a value higher than [code]0[/code], this will make glow visible in areas darker than the [member glow_hdr_threshold].
</member>
<member name="glow_enabled" type="bool" setter="set_glow_enabled" getter="is_glow_enabled" default="false">
- Enables glow rendering.
+ If [code]true[/code], the glow effect is enabled.
</member>
<member name="glow_hdr_luminance_cap" type="float" setter="set_glow_hdr_luminance_cap" getter="get_glow_hdr_luminance_cap" default="12.0">
+ The higher threshold of the HDR glow. Areas brighter than this threshold will be clamped for the purposes of the glow effect.
</member>
<member name="glow_hdr_scale" type="float" setter="set_glow_hdr_bleed_scale" getter="get_glow_hdr_bleed_scale" default="2.0">
- Bleed scale of the HDR glow.
+ The bleed scale of the HDR glow.
</member>
<member name="glow_hdr_threshold" type="float" setter="set_glow_hdr_bleed_threshold" getter="get_glow_hdr_bleed_threshold" default="1.0">
- Bleed threshold of the HDR glow. In GLES2, this needs to be below 1.0 in order for glow to be visible, a default value of 0.9 works well.
+ The lower threshold of the HDR glow. When using the GLES2 renderer (which doesn't support HDR), this needs to be below [code]1.0[/code] for glow to be visible. A value of [code]0.9[/code] works well in this case.
</member>
<member name="glow_intensity" type="float" setter="set_glow_intensity" getter="get_glow_intensity" default="0.8">
- Glow intensity. In GLES2, this should be increased to 1.5 by default to compensate for not using HDR.
+ The glow intensity. When using the GLES2 renderer, this should be increased to 1.5 to compensate for the lack of HDR rendering.
</member>
<member name="glow_levels/1" type="bool" setter="set_glow_level" getter="is_glow_level_enabled" default="false">
- First level of glow (most local).
+ If [code]true[/code], the 1st level of glow is enabled. This is the most "local" level (least blurry).
</member>
<member name="glow_levels/2" type="bool" setter="set_glow_level" getter="is_glow_level_enabled" default="false">
- Second level of glow.
+ If [code]true[/code], the 2th level of glow is enabled.
</member>
<member name="glow_levels/3" type="bool" setter="set_glow_level" getter="is_glow_level_enabled" default="true">
- Third level of glow.
+ If [code]true[/code], the 3th level of glow is enabled.
</member>
<member name="glow_levels/4" type="bool" setter="set_glow_level" getter="is_glow_level_enabled" default="false">
- Fourth level of glow.
+ If [code]true[/code], the 4th level of glow is enabled.
</member>
<member name="glow_levels/5" type="bool" setter="set_glow_level" getter="is_glow_level_enabled" default="true">
- Fifth level of glow.
+ If [code]true[/code], the 5th level of glow is enabled.
</member>
<member name="glow_levels/6" type="bool" setter="set_glow_level" getter="is_glow_level_enabled" default="false">
- Sixth level of glow.
+ If [code]true[/code], the 6th level of glow is enabled.
</member>
<member name="glow_levels/7" type="bool" setter="set_glow_level" getter="is_glow_level_enabled" default="false">
- Seventh level of glow (most global).
+ If [code]true[/code], the 7th level of glow is enabled. This is the most "global" level (blurriest).
</member>
<member name="glow_strength" type="float" setter="set_glow_strength" getter="get_glow_strength" default="1.0">
- Glow strength. In GLES2, this should be increased to 1.3 by default to compensate for not using HDR.
+ The glow strength. When using the GLES2 renderer, this should be increased to 1.3 to compensate for the lack of HDR rendering.
</member>
<member name="ss_reflections_depth_tolerance" type="float" setter="set_ssr_depth_tolerance" getter="get_ssr_depth_tolerance" default="0.2">
+ The depth tolerance for screen-space reflections.
</member>
<member name="ss_reflections_enabled" type="bool" setter="set_ssr_enabled" getter="is_ssr_enabled" default="false">
+ If [code]true[/code], screen-space reflections are enabled. Screen-space reflections are more accurate than reflections from [GIProbe]s or [ReflectionProbe]s, but are slower and can't reflect surfaces occluded by others.
</member>
<member name="ss_reflections_fade_in" type="float" setter="set_ssr_fade_in" getter="get_ssr_fade_in" default="0.15">
+ The fade-in distance for screen-space reflections. Affects the area from the reflected material to the screen-space reflection).
</member>
<member name="ss_reflections_fade_out" type="float" setter="set_ssr_fade_out" getter="get_ssr_fade_out" default="2.0">
+ The fade-out distance for screen-space reflections. Affects the area from the screen-space reflection to the "global" reflection.
</member>
<member name="ss_reflections_max_steps" type="int" setter="set_ssr_max_steps" getter="get_ssr_max_steps" default="64">
+ The maximum number of steps for screen-space reflections. Higher values are slower.
</member>
<member name="ss_reflections_roughness" type="bool" setter="set_ssr_rough" getter="is_ssr_rough" default="true">
+ If [code]true[/code], screen-space reflections will take the material roughness into account.
</member>
<member name="ssao_ao_channel_affect" type="float" setter="set_ssao_ao_channel_affect" getter="get_ssao_ao_channel_affect" default="0.0">
+ The screen-space ambient occlusion intensity on materials that have an AO texture defined. Values higher than [code]0[/code] will make the SSAO effect visible in areas darkened by AO textures.
</member>
<member name="ssao_bias" type="float" setter="set_ssao_bias" getter="get_ssao_bias" default="0.01">
+ The screen-space ambient occlusion bias. This should be kept high enough to prevent "smooth" curves from being affected by ambient occlusion.
</member>
<member name="ssao_blur" type="int" setter="set_ssao_blur" getter="get_ssao_blur" enum="Environment.SSAOBlur" default="3">
+ The screen-space ambient occlusion blur quality. See [enum SSAOBlur] for possible values.
</member>
<member name="ssao_color" type="Color" setter="set_ssao_color" getter="get_ssao_color" default="Color( 0, 0, 0, 1 )">
+ The screen-space ambient occlusion color.
</member>
<member name="ssao_edge_sharpness" type="float" setter="set_ssao_edge_sharpness" getter="get_ssao_edge_sharpness" default="4.0">
+ The screen-space ambient occlusion edge sharpness.
</member>
<member name="ssao_enabled" type="bool" setter="set_ssao_enabled" getter="is_ssao_enabled" default="false">
+ If [code]true[/code], the screen-space ambient occlusion effect is enabled. This darkens objects' corners and cavities to simulate ambient light not reaching the entire object as in real life. This works well for small, dynamic objects, but baked lighting or ambient occlusion textures will do a better job at displaying ambient occlusion on large static objects. This is a costly effect and should be disabled first when running into performance issues.
</member>
<member name="ssao_intensity" type="float" setter="set_ssao_intensity" getter="get_ssao_intensity" default="1.0">
+ The primary screen-space ambient occlusion intensity. See also [member ssao_radius].
</member>
<member name="ssao_intensity2" type="float" setter="set_ssao_intensity2" getter="get_ssao_intensity2" default="1.0">
+ The secondary screen-space ambient occlusion intensity. See also [member ssao_radius2].
</member>
<member name="ssao_light_affect" type="float" setter="set_ssao_direct_light_affect" getter="get_ssao_direct_light_affect" default="0.0">
+ The screen-space ambient occlusion intensity in direct light. In real life, ambient occlusion only applies to indirect light, which means its effects can't be seen in direct light. Values higher than [code]0[/code] will make the SSAO effect visible in direct light.
</member>
<member name="ssao_quality" type="int" setter="set_ssao_quality" getter="get_ssao_quality" enum="Environment.SSAOQuality" default="1">
+ The screen-space ambient occlusion quality. Higher qualities will make better use of small objects for ambient occlusion, but are slower.
</member>
<member name="ssao_radius" type="float" setter="set_ssao_radius" getter="get_ssao_radius" default="1.0">
+ The primary screen-space ambient occlusion radius.
</member>
<member name="ssao_radius2" type="float" setter="set_ssao_radius2" getter="get_ssao_radius2" default="0.0">
+ The secondary screen-space ambient occlusion radius. If set to a value higher than [code]0[/code], enables the secondary screen-space ambient occlusion effect which can be used to improve the effect's appearance (at the cost of performance).
</member>
<member name="tonemap_exposure" type="float" setter="set_tonemap_exposure" getter="get_tonemap_exposure" default="1.0">
- Default exposure for tonemap.
+ The default exposure used for tonemapping.
</member>
<member name="tonemap_mode" type="int" setter="set_tonemapper" getter="get_tonemapper" enum="Environment.ToneMapper" default="0">
- Tonemapping mode.
+ The tonemapping mode to use. Tonemapping is the process that "converts" HDR values to be suitable for rendering on a LDR display. (Godot doesn't support rendering on HDR displays yet.)
</member>
<member name="tonemap_white" type="float" setter="set_tonemap_white" getter="get_tonemap_white" default="1.0">
- White reference value for tonemap.
+ The white reference value for tonemapping. Only effective if the [member tonemap_mode] isn't set to [constant TONE_MAPPER_LINEAR].
</member>
</members>
<constants>
<constant name="BG_KEEP" value="5" enum="BGMode">
- Keep on screen every pixel drawn in the background.
+ Keeps on screen every pixel drawn in the background. This is the fastest background mode, but it can only be safely used in fully-interior scenes (no visible sky or sky reflections). If enabled in a scene where the background is visible, "ghost trail" artifacts will be visible when moving the camera.
</constant>
<constant name="BG_CLEAR_COLOR" value="0" enum="BGMode">
- Clear the background using the project's clear color.
+ Clears the background using the clear color defined in [member ProjectSettings.rendering/environment/default_clear_color].
</constant>
<constant name="BG_COLOR" value="1" enum="BGMode">
- Clear the background using a custom clear color.
+ Clears the background using a custom clear color.
</constant>
<constant name="BG_SKY" value="2" enum="BGMode">
- Display a user-defined sky in the background.
+ Displays a user-defined sky in the background.
</constant>
<constant name="BG_COLOR_SKY" value="3" enum="BGMode">
- Clear the background using a custom clear color and allows defining a sky for shading and reflection.
+ Clears the background using a custom clear color and allows defining a sky for shading and reflection. This mode is slightly faster than [constant BG_SKY] and should be preferred in scenes where reflections can be visible, but the sky itself never is (e.g. top-down camera).
</constant>
<constant name="BG_CANVAS" value="4" enum="BGMode">
- Display a [CanvasLayer] in the background.
+ Displays a [CanvasLayer] in the background.
</constant>
<constant name="BG_CAMERA_FEED" value="6" enum="BGMode">
- Display a camera feed in the background.
+ Displays a camera feed in the background.
</constant>
<constant name="BG_MAX" value="7" enum="BGMode">
Represents the size of the [enum BGMode] enum.
@@ -301,10 +323,10 @@
Screen glow blending mode. Increases brightness, used frequently with bloom.
</constant>
<constant name="GLOW_BLEND_MODE_SOFTLIGHT" value="2" enum="GlowBlendMode">
- Soft light glow blending mode. Modifies contrast, exposes shadows and highlights, vivid bloom.
+ Soft light glow blending mode. Modifies contrast, exposes shadows and highlights (vivid bloom).
</constant>
<constant name="GLOW_BLEND_MODE_REPLACE" value="3" enum="GlowBlendMode">
- Replace glow blending mode. Replaces all pixels' color by the glow value.
+ Replace glow blending mode. Replaces all pixels' color by the glow value. This can be used to simulate a full-screen blur effect by tweaking the glow parameters to match the original image's brightness.
</constant>
<constant name="TONE_MAPPER_LINEAR" value="0" enum="ToneMapper">
Linear tonemapper operator. Reads the linear data and passes it on unmodified.
@@ -319,27 +341,34 @@
Academy Color Encoding System tonemapper operator.
</constant>
<constant name="DOF_BLUR_QUALITY_LOW" value="0" enum="DOFBlurQuality">
- Low depth-of-field blur quality.
+ Low depth-of-field blur quality (fastest).
</constant>
<constant name="DOF_BLUR_QUALITY_MEDIUM" value="1" enum="DOFBlurQuality">
Medium depth-of-field blur quality.
</constant>
<constant name="DOF_BLUR_QUALITY_HIGH" value="2" enum="DOFBlurQuality">
- High depth-of-field blur quality.
+ High depth-of-field blur quality (slowest).
</constant>
<constant name="SSAO_BLUR_DISABLED" value="0" enum="SSAOBlur">
+ No blur for the screen-space ambient occlusion effect (fastest).
</constant>
<constant name="SSAO_BLUR_1x1" value="1" enum="SSAOBlur">
+ 1×1 blur for the screen-space ambient occlusion effect.
</constant>
<constant name="SSAO_BLUR_2x2" value="2" enum="SSAOBlur">
+ 2×2 blur for the screen-space ambient occlusion effect.
</constant>
<constant name="SSAO_BLUR_3x3" value="3" enum="SSAOBlur">
+ 3×3 blur for the screen-space ambient occlusion effect (slowest).
</constant>
<constant name="SSAO_QUALITY_LOW" value="0" enum="SSAOQuality">
+ Low quality for the screen-space ambient occlusion effect (fastest).
</constant>
<constant name="SSAO_QUALITY_MEDIUM" value="1" enum="SSAOQuality">
+ Low quality for the screen-space ambient occlusion effect.
</constant>
<constant name="SSAO_QUALITY_HIGH" value="2" enum="SSAOQuality">
+ Low quality for the screen-space ambient occlusion effect (slowest).
</constant>
</constants>
</class>
diff --git a/doc/classes/Font.xml b/doc/classes/Font.xml
index f7de79913c..e751a07082 100644
--- a/doc/classes/Font.xml
+++ b/doc/classes/Font.xml
@@ -91,6 +91,7 @@
<return type="bool">
</return>
<description>
+ Returns [code]true[/code] if the font has an outline.
</description>
</method>
<method name="is_distance_field_hint" qualifiers="const">
diff --git a/doc/classes/Geometry.xml b/doc/classes/Geometry.xml
index 3824baa4dc..dbc06f7c4f 100644
--- a/doc/classes/Geometry.xml
+++ b/doc/classes/Geometry.xml
@@ -1,8 +1,10 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="Geometry" inherits="Object" category="Core" version="3.2">
<brief_description>
+ Helper node to calculate generic geometry operations.
</brief_description>
<description>
+ Geometry provides users with a set of helper functions to create geometric shapes, compute intersections between shapes, and process various other geometric operations.
</description>
<tutorials>
</tutorials>
diff --git a/doc/classes/GeometryInstance.xml b/doc/classes/GeometryInstance.xml
index 02f2c27043..980815e5fd 100644
--- a/doc/classes/GeometryInstance.xml
+++ b/doc/classes/GeometryInstance.xml
@@ -15,6 +15,7 @@
<argument index="0" name="flag" type="int" enum="GeometryInstance.Flags">
</argument>
<description>
+ Returns the [enum GeometryInstance.Flags] that have been set for this object.
</description>
</method>
<method name="set_custom_aabb">
@@ -34,6 +35,7 @@
<argument index="1" name="value" type="bool">
</argument>
<description>
+ Sets the [enum GeometryInstance.Flags] specified. See [enum GeometryInstance.Flags] for options.
</description>
</method>
</methods>
diff --git a/doc/classes/GraphEdit.xml b/doc/classes/GraphEdit.xml
index 3041a7cb7f..802134d3b6 100644
--- a/doc/classes/GraphEdit.xml
+++ b/doc/classes/GraphEdit.xml
@@ -160,6 +160,7 @@
<argument index="4" name="amount" type="float">
</argument>
<description>
+ Sets the coloration of the connection between [code]from[/code]'s [code]from_port[/code] and [code]to[/code]'s [code]to_port[/code] with the color provided in the [code]activity[/code] theme property.
</description>
</method>
<method name="set_selected">
@@ -194,12 +195,12 @@
<signals>
<signal name="_begin_node_move">
<description>
- Signal sent at the beginning of a GraphNode movement.
+ Emitted at the beginning of a GraphNode movement.
</description>
</signal>
<signal name="_end_node_move">
<description>
- Signal sent at the end of a GraphNode movement.
+ Emitted at the end of a GraphNode movement.
</description>
</signal>
<signal name="connection_from_empty">
@@ -210,7 +211,7 @@
<argument index="2" name="release_position" type="Vector2">
</argument>
<description>
- Signal sent when user dragging connection from input port into empty space of the graph.
+ Emitted when user dragging connection from input port into empty space of the graph.
</description>
</signal>
<signal name="connection_request">
@@ -223,7 +224,7 @@
<argument index="3" name="to_slot" type="int">
</argument>
<description>
- Signal sent to the GraphEdit when the connection between the [code]from_slot[/code] slot of the [code]from[/code] GraphNode and the [code]to_slot[/code] slot of the [code]to[/code] GraphNode is attempted to be created.
+ Emitted to the GraphEdit when the connection between the [code]from_slot[/code] slot of the [code]from[/code] GraphNode and the [code]to_slot[/code] slot of the [code]to[/code] GraphNode is attempted to be created.
</description>
</signal>
<signal name="connection_to_empty">
@@ -234,17 +235,17 @@
<argument index="2" name="release_position" type="Vector2">
</argument>
<description>
- Signal sent when user dragging connection from output port into empty space of the graph.
+ Emitted when user dragging connection from output port into empty space of the graph.
</description>
</signal>
<signal name="copy_nodes_request">
<description>
- Signal sent when the user presses [code]Ctrl + C[/code].
+ Emitted when the user presses [code]Ctrl + C[/code].
</description>
</signal>
<signal name="delete_nodes_request">
<description>
- Signal sent when a GraphNode is attempted to be removed from the GraphEdit.
+ Emitted when a GraphNode is attempted to be removed from the GraphEdit.
</description>
</signal>
<signal name="disconnection_request">
@@ -274,7 +275,7 @@
</signal>
<signal name="paste_nodes_request">
<description>
- Signal sent when the user presses [code]Ctrl + V[/code].
+ Emitted when the user presses [code]Ctrl + V[/code].
</description>
</signal>
<signal name="popup_request">
@@ -288,6 +289,7 @@
<argument index="0" name="ofs" type="Vector2">
</argument>
<description>
+ Emitted when the scroll offset is changed by the user. It will not be emitted when changed in code.
</description>
</signal>
</signals>
@@ -316,6 +318,10 @@
</theme_item>
<theme_item name="reset" type="Texture">
</theme_item>
+ <theme_item name="selection_fill" type="Color" default="Color( 1, 1, 1, 0.3 )">
+ </theme_item>
+ <theme_item name="selection_stroke" type="Color" default="Color( 1, 1, 1, 0.8 )">
+ </theme_item>
<theme_item name="snap" type="Texture">
</theme_item>
</theme_items>
diff --git a/doc/classes/GraphNode.xml b/doc/classes/GraphNode.xml
index 77b3eb1ca0..8fda9c20a5 100644
--- a/doc/classes/GraphNode.xml
+++ b/doc/classes/GraphNode.xml
@@ -170,12 +170,12 @@
<argument index="8" name="custom_right" type="Texture" default="null">
</argument>
<description>
- Sets properties of the slot with id [code]idx[/code].
+ Sets properties of the slot with ID [code]idx[/code].
If [code]enable_left[/code]/[code]right[/code], a port will appear and the slot will be able to be connected from this side.
[code]type_left[/code]/[code]right[/code] is an arbitrary type of the port. Only ports with the same type values can be connected.
[code]color_left[/code]/[code]right[/code] is the tint of the port's icon on this side.
[code]custom_left[/code]/[code]right[/code] is a custom texture for this side's port.
- [b]Note:[/b] this method only sets properties of the slot. To create the slot, add a [Control]-derived child to the GraphNode.
+ [b]Note:[/b] This method only sets properties of the slot. To create the slot, add a [Control]-derived child to the GraphNode.
</description>
</method>
</methods>
@@ -188,20 +188,27 @@
[b]Note:[/b] You cannot use position directly, as [GraphEdit] is a [Container].
</member>
<member name="overlay" type="int" setter="set_overlay" getter="get_overlay" enum="GraphNode.Overlay" default="0">
+ Sets the overlay shown above the GraphNode. See [enum Overlay].
</member>
<member name="resizable" type="bool" setter="set_resizable" getter="is_resizable" default="false">
+ If [code]true[/code], the user can resize the GraphNode.
+ [b]Note:[/b] Dragging the handle will only trigger the [signal resize_request] signal, the GraphNode needs to be resized manually.
</member>
<member name="selected" type="bool" setter="set_selected" getter="is_selected" default="false">
+ If [code]true[/code], the GraphNode is selected.
</member>
<member name="show_close" type="bool" setter="set_show_close_button" getter="is_close_button_visible" default="false">
+ If [code]true[/code], the close button will be visible.
+ [b]Note:[/b] Pressing it will only trigger the [signal close_request] signal, the GraphNode needs to be removed manually.
</member>
<member name="title" type="String" setter="set_title" getter="get_title" default="&quot;&quot;">
+ The text displayed in the GraphNode's title bar.
</member>
</members>
<signals>
<signal name="close_request">
<description>
- Signal sent on closing the GraphNode.
+ Emitted when the GraphNode is requested to be closed. Happens on clicking the close button (see [member show_close]).
</description>
</signal>
<signal name="dragged">
@@ -210,32 +217,36 @@
<argument index="1" name="to" type="Vector2">
</argument>
<description>
- Signal sent when the GraphNode is dragged.
+ Emitted when the GraphNode is dragged.
</description>
</signal>
<signal name="offset_changed">
<description>
- Signal sent when the GraphNode is moved.
+ Emitted when the GraphNode is moved.
</description>
</signal>
<signal name="raise_request">
<description>
- Signal sent when the GraphNode is requested to be displayed over other ones. Happens on focusing (clicking into) the GraphNode.
+ Emitted when the GraphNode is requested to be displayed over other ones. Happens on focusing (clicking into) the GraphNode.
</description>
</signal>
<signal name="resize_request">
<argument index="0" name="new_minsize" type="Vector2">
</argument>
<description>
+ Emitted when the GraphNode is requested to be resized. Happens on dragging the resizer handle (see [member resizable]).
</description>
</signal>
</signals>
<constants>
<constant name="OVERLAY_DISABLED" value="0" enum="Overlay">
+ No overlay is shown.
</constant>
<constant name="OVERLAY_BREAKPOINT" value="1" enum="Overlay">
+ Show overlay set in the [code]breakpoint[/code] theme property.
</constant>
<constant name="OVERLAY_POSITION" value="2" enum="Overlay">
+ Show overlay set in the [code]position[/code] theme property.
</constant>
</constants>
<theme_items>
diff --git a/doc/classes/HScrollBar.xml b/doc/classes/HScrollBar.xml
index 14ace8bc76..90f14dd344 100644
--- a/doc/classes/HScrollBar.xml
+++ b/doc/classes/HScrollBar.xml
@@ -4,7 +4,7 @@
Horizontal scroll bar.
</brief_description>
<description>
- Horizontal scroll bar. See [ScrollBar]. This one goes from left (min) to right (max).
+ Horizontal version of [ScrollBar], which goes from left (min) to right (max).
</description>
<tutorials>
</tutorials>
@@ -14,22 +14,31 @@
</constants>
<theme_items>
<theme_item name="decrement" type="Texture">
+ Icon used as a button to scroll the [ScrollBar] left. Supports custom step using the [member ScrollBar.custom_step] property.
</theme_item>
<theme_item name="decrement_highlight" type="Texture">
+ Displayed when the mouse cursor hovers over the decrement button.
</theme_item>
<theme_item name="grabber" type="StyleBox">
+ Used as texture for the grabber, the draggable element representing current scroll.
</theme_item>
<theme_item name="grabber_highlight" type="StyleBox">
+ Used when the mouse hovers over the grabber.
</theme_item>
<theme_item name="grabber_pressed" type="StyleBox">
+ Used when the grabber is being dragged.
</theme_item>
<theme_item name="increment" type="Texture">
+ Icon used as a button to scroll the [ScrollBar] right. Supports custom step using the [member ScrollBar.custom_step] property.
</theme_item>
<theme_item name="increment_highlight" type="Texture">
+ Displayed when the mouse cursor hovers over the increment button.
</theme_item>
<theme_item name="scroll" type="StyleBox">
+ Used as background of this [ScrollBar].
</theme_item>
<theme_item name="scroll_focus" type="StyleBox">
+ Used as background when the [ScrollBar] has the GUI focus.
</theme_item>
</theme_items>
</class>
diff --git a/doc/classes/HashingContext.xml b/doc/classes/HashingContext.xml
index 802b186ef3..8a20eb99b8 100644
--- a/doc/classes/HashingContext.xml
+++ b/doc/classes/HashingContext.xml
@@ -27,6 +27,7 @@
# Print the result as hex string and array.
printt(res.hex_encode(), Array(res))
[/codeblock]
+ [b]Note:[/b] Not available in HTML5 exports.
</description>
<tutorials>
</tutorials>
diff --git a/doc/classes/Image.xml b/doc/classes/Image.xml
index 0303585120..612b9ed3f5 100644
--- a/doc/classes/Image.xml
+++ b/doc/classes/Image.xml
@@ -71,6 +71,7 @@
<argument index="0" name="bump_scale" type="float" default="1.0">
</argument>
<description>
+ Converts a bumpmap to a normalmap. A bumpmap provides a height offset per-pixel, while a normalmap provides a normal direction per pixel.
</description>
</method>
<method name="clear_mipmaps">
@@ -165,7 +166,7 @@
<return type="int" enum="Image.AlphaMode">
</return>
<description>
- Returns [constant ALPHA_BLEND] if the image has data for alpha values. Returns [constant ALPHA_BIT] if all the alpha values are below a certain threshold or the maximum value. Returns [constant ALPHA_NONE] if no data for alpha values is found.
+ Returns [constant ALPHA_BLEND] if the image has data for alpha values. Returns [constant ALPHA_BIT] if all the alpha values are stored in a single bit. Returns [constant ALPHA_NONE] if no data for alpha values is found.
</description>
</method>
<method name="expand_x2_hq2x">
@@ -405,6 +406,7 @@
<return type="Image">
</return>
<description>
+ Converts a standard RGBE (Red Green Blue Exponent) image to an sRGB image.
</description>
</method>
<method name="save_exr" qualifiers="const">
@@ -502,8 +504,10 @@
The maximal height allowed for [Image] resources.
</constant>
<constant name="FORMAT_L8" value="0" enum="Format">
+ Texture format with a single 8-bit depth representing luminance.
</constant>
<constant name="FORMAT_LA8" value="1" enum="Format">
+ OpenGL texture format with two values, luminance and alpha each stored with 8 bits.
</constant>
<constant name="FORMAT_R8" value="2" enum="Format">
OpenGL texture format [code]RED[/code] with a single component and a bitdepth of 8.
@@ -643,26 +647,37 @@
Performs Lanczos interpolation. This is the slowest image resizing mode, but it typically gives the best results, especially when downscalng images.
</constant>
<constant name="ALPHA_NONE" value="0" enum="AlphaMode">
+ Image does not have alpha.
</constant>
<constant name="ALPHA_BIT" value="1" enum="AlphaMode">
+ Image stores alpha in a single bit.
</constant>
<constant name="ALPHA_BLEND" value="2" enum="AlphaMode">
+ Image uses alpha.
</constant>
<constant name="COMPRESS_S3TC" value="0" enum="CompressMode">
+ Use S3TC compression.
</constant>
<constant name="COMPRESS_PVRTC2" value="1" enum="CompressMode">
+ Use PVRTC2 compression.
</constant>
<constant name="COMPRESS_PVRTC4" value="2" enum="CompressMode">
+ Use PVRTC4 compression.
</constant>
<constant name="COMPRESS_ETC" value="3" enum="CompressMode">
+ Use ETC compression.
</constant>
<constant name="COMPRESS_ETC2" value="4" enum="CompressMode">
+ Use ETC2 compression.
</constant>
<constant name="COMPRESS_SOURCE_GENERIC" value="0" enum="CompressSource">
+ Source texture (before compression) is a regular texture. Default for all textures.
</constant>
<constant name="COMPRESS_SOURCE_SRGB" value="1" enum="CompressSource">
+ Source texture (before compression) is in sRGB space.
</constant>
<constant name="COMPRESS_SOURCE_NORMAL" value="2" enum="CompressSource">
+ Source texture (before compression) is a normal texture (e.g. it can be compressed into two channels).
</constant>
</constants>
</class>
diff --git a/doc/classes/InputMap.xml b/doc/classes/InputMap.xml
index 6bbb402b15..5b83f943cf 100644
--- a/doc/classes/InputMap.xml
+++ b/doc/classes/InputMap.xml
@@ -60,6 +60,7 @@
<argument index="1" name="deadzone" type="float">
</argument>
<description>
+ Sets a deadzone value for the action.
</description>
</method>
<method name="add_action">
diff --git a/doc/classes/KinematicBody.xml b/doc/classes/KinematicBody.xml
index 164932749f..c32264221d 100644
--- a/doc/classes/KinematicBody.xml
+++ b/doc/classes/KinematicBody.xml
@@ -21,11 +21,18 @@
Returns [code]true[/code] if the specified [code]axis[/code] is locked. See also [member move_lock_x], [member move_lock_y] and [member move_lock_z].
</description>
</method>
+ <method name="get_floor_normal" qualifiers="const">
+ <return type="Vector3">
+ </return>
+ <description>
+ Returns the surface normal of the floor at the last collision point. Only valid after calling [method move_and_slide] or [method move_and_slide_with_snap] and when [method is_on_floor] returns [code]true[/code].
+ </description>
+ </method>
<method name="get_floor_velocity" qualifiers="const">
<return type="Vector3">
</return>
<description>
- Returns the velocity of the floor. Only updates when calling [method move_and_slide].
+ Returns the linear velocity of the floor at the last collision point. Only valid after calling [method move_and_slide] or [method move_and_slide_with_snap] and when [method is_on_floor] returns [code]true[/code].
</description>
</method>
<method name="get_slide_collision">
@@ -86,7 +93,7 @@
</return>
<argument index="0" name="linear_velocity" type="Vector3">
</argument>
- <argument index="1" name="floor_normal" type="Vector3" default="Vector3( 0, 0, 0 )">
+ <argument index="1" name="up_direction" type="Vector3" default="Vector3( 0, 0, 0 )">
</argument>
<argument index="2" name="stop_on_slope" type="bool" default="false">
</argument>
@@ -99,7 +106,7 @@
<description>
Moves the body along a vector. If the body collides with another, it will slide along the other body rather than stop immediately. If the other body is a [KinematicBody] or [RigidBody], it will also be affected by the motion of the other body. You can use this to make moving or rotating platforms, or to make nodes push other nodes.
[code]linear_velocity[/code] is the velocity vector (typically meters per second). Unlike in [method move_and_collide], you should [i]not[/i] multiply it by [code]delta[/code] — the physics engine handles applying the velocity.
- [code]floor_normal[/code] is the up direction, used to determine what is a wall and what is a floor or a ceiling. If set to the default value of [code]Vector3(0, 0, 0)[/code], everything is considered a wall. This is useful for topdown games.
+ [code]up_direction[/code] is the up direction, used to determine what is a wall and what is a floor or a ceiling. If set to the default value of [code]Vector3(0, 0, 0)[/code], everything is considered a wall.
If [code]stop_on_slope[/code] is [code]true[/code], body will not slide on slopes if you include gravity in [code]linear_velocity[/code].
If the body collides, it will change direction a maximum of [code]max_slides[/code] times before it stops.
[code]floor_max_angle[/code] is the maximum angle (in radians) where a slope is still considered a floor (or a ceiling), rather than a wall. The default value equals 45 degrees.
@@ -114,7 +121,7 @@
</argument>
<argument index="1" name="snap" type="Vector3">
</argument>
- <argument index="2" name="floor_normal" type="Vector3" default="Vector3( 0, 0, 0 )">
+ <argument index="2" name="up_direction" type="Vector3" default="Vector3( 0, 0, 0 )">
</argument>
<argument index="3" name="stop_on_slope" type="bool" default="false">
</argument>
diff --git a/doc/classes/KinematicBody2D.xml b/doc/classes/KinematicBody2D.xml
index 99a83765eb..6a3b3dabb1 100644
--- a/doc/classes/KinematicBody2D.xml
+++ b/doc/classes/KinematicBody2D.xml
@@ -13,11 +13,18 @@
<link>https://docs.godotengine.org/en/latest/tutorials/physics/using_kinematic_body_2d.html</link>
</tutorials>
<methods>
+ <method name="get_floor_normal" qualifiers="const">
+ <return type="Vector2">
+ </return>
+ <description>
+ Returns the surface normal of the floor at the last collision point. Only valid after calling [method move_and_slide] or [method move_and_slide_with_snap] and when [method is_on_floor] returns [code]true[/code].
+ </description>
+ </method>
<method name="get_floor_velocity" qualifiers="const">
<return type="Vector2">
</return>
<description>
- Returns the velocity of the floor. Only updates when calling [method move_and_slide].
+ Returns the linear velocity of the floor at the last collision point. Only valid after calling [method move_and_slide] or [method move_and_slide_with_snap] and when [method is_on_floor] returns [code]true[/code].
</description>
</method>
<method name="get_slide_collision">
@@ -84,7 +91,7 @@
</return>
<argument index="0" name="linear_velocity" type="Vector2">
</argument>
- <argument index="1" name="floor_normal" type="Vector2" default="Vector2( 0, 0 )">
+ <argument index="1" name="up_direction" type="Vector2" default="Vector2( 0, 0 )">
</argument>
<argument index="2" name="stop_on_slope" type="bool" default="false">
</argument>
@@ -97,7 +104,7 @@
<description>
Moves the body along a vector. If the body collides with another, it will slide along the other body rather than stop immediately. If the other body is a [KinematicBody2D] or [RigidBody2D], it will also be affected by the motion of the other body. You can use this to make moving or rotating platforms, or to make nodes push other nodes.
[code]linear_velocity[/code] is the velocity vector in pixels per second. Unlike in [method move_and_collide], you should [i]not[/i] multiply it by [code]delta[/code] — the physics engine handles applying the velocity.
- [code]floor_normal[/code] is the up direction, used to determine what is a wall and what is a floor or a ceiling. If set to the default value of [code]Vector2(0, 0)[/code], everything is considered a wall. This is useful for topdown games.
+ [code]up_direction[/code] is the up direction, used to determine what is a wall and what is a floor or a ceiling. If set to the default value of [code]Vector2(0, 0)[/code], everything is considered a wall. This is useful for topdown games.
If [code]stop_on_slope[/code] is [code]true[/code], body will not slide on slopes when you include gravity in [code]linear_velocity[/code] and the body is standing still.
If the body collides, it will change direction a maximum of [code]max_slides[/code] times before it stops.
[code]floor_max_angle[/code] is the maximum angle (in radians) where a slope is still considered a floor (or a ceiling), rather than a wall. The default value equals 45 degrees.
@@ -112,7 +119,7 @@
</argument>
<argument index="1" name="snap" type="Vector2">
</argument>
- <argument index="2" name="floor_normal" type="Vector2" default="Vector2( 0, 0 )">
+ <argument index="2" name="up_direction" type="Vector2" default="Vector2( 0, 0 )">
</argument>
<argument index="3" name="stop_on_slope" type="bool" default="false">
</argument>
diff --git a/doc/classes/Light.xml b/doc/classes/Light.xml
index 6ef7c2652d..ae5bba4f06 100644
--- a/doc/classes/Light.xml
+++ b/doc/classes/Light.xml
@@ -16,6 +16,7 @@
<argument index="0" name="param" type="int" enum="Light.Param">
</argument>
<description>
+ Returns the value of the specified [enum Light.Param] parameter.
</description>
</method>
<method name="set_param">
@@ -26,6 +27,7 @@
<argument index="1" name="value" type="float">
</argument>
<description>
+ Sets the value of the specified [enum Light.Param] parameter.
</description>
</method>
</methods>
@@ -67,38 +69,54 @@
If [code]true[/code], the light will cast shadows.
</member>
<member name="shadow_reverse_cull_face" type="bool" setter="set_shadow_reverse_cull_face" getter="get_shadow_reverse_cull_face" default="false">
+ If [code]true[/code], reverses the backface culling of the mesh. This can be useful when you have a flat mesh that has a light behind it. If you need to cast a shadow on both sides of the mesh, set the mesh to use double-sided shadows with [constant GeometryInstance.SHADOW_CASTING_SETTING_DOUBLE_SIDED].
</member>
</members>
<constants>
<constant name="PARAM_ENERGY" value="0" enum="Param">
+ Constant for accessing [member light_energy].
</constant>
<constant name="PARAM_INDIRECT_ENERGY" value="1" enum="Param">
+ Constant for accessing [member light_indirect_energy].
</constant>
<constant name="PARAM_SPECULAR" value="2" enum="Param">
+ Constant for accessing [member light_specular].
</constant>
<constant name="PARAM_RANGE" value="3" enum="Param">
+ Constant for accessing [member OmniLight.omni_range] or [member SpotLight.spot_range].
</constant>
<constant name="PARAM_ATTENUATION" value="4" enum="Param">
+ Constant for accessing [member OmniLight.omni_attenuation] or [member SpotLight.spot_attenuation].
</constant>
<constant name="PARAM_SPOT_ANGLE" value="5" enum="Param">
+ Constant for accessing [member SpotLight.spot_angle].
</constant>
<constant name="PARAM_SPOT_ATTENUATION" value="6" enum="Param">
+ Constant for accessing [member SpotLight.spot_angle_attenuation].
</constant>
<constant name="PARAM_CONTACT_SHADOW_SIZE" value="7" enum="Param">
+ Constant for accessing [member shadow_contact].
</constant>
<constant name="PARAM_SHADOW_MAX_DISTANCE" value="8" enum="Param">
+ Constant for accessing [member DirectionalLight.directional_shadow_max_distance].
</constant>
<constant name="PARAM_SHADOW_SPLIT_1_OFFSET" value="9" enum="Param">
+ Constant for accessing [member DirectionalLight.directional_shadow_split_1].
</constant>
<constant name="PARAM_SHADOW_SPLIT_2_OFFSET" value="10" enum="Param">
+ Constant for accessing [member DirectionalLight.directional_shadow_split_2].
</constant>
<constant name="PARAM_SHADOW_SPLIT_3_OFFSET" value="11" enum="Param">
+ Constant for accessing [member DirectionalLight.directional_shadow_split_3].
</constant>
<constant name="PARAM_SHADOW_NORMAL_BIAS" value="12" enum="Param">
+ Constant for accessing [member DirectionalLight.directional_shadow_normal_bias].
</constant>
<constant name="PARAM_SHADOW_BIAS" value="13" enum="Param">
+ Constant for accessing [member shadow_bias].
</constant>
<constant name="PARAM_SHADOW_BIAS_SPLIT_SCALE" value="14" enum="Param">
+ Constant for accessing [member DirectionalLight.directional_shadow_bias_split_scale].
</constant>
<constant name="PARAM_MAX" value="15" enum="Param">
Represents the size of the [enum Param] enum.
diff --git a/doc/classes/LineEdit.xml b/doc/classes/LineEdit.xml
index 78459d2839..31cfc15649 100644
--- a/doc/classes/LineEdit.xml
+++ b/doc/classes/LineEdit.xml
@@ -96,7 +96,7 @@
The cursor's position inside the [LineEdit]. When set, the text may scroll to accommodate it.
</member>
<member name="clear_button_enabled" type="bool" setter="set_clear_button_enabled" getter="is_clear_button_enabled" default="false">
- If [code]true[/code], the [LineEdit] will show a clear button if [code]text[/code] is not empty.
+ If [code]true[/code], the [LineEdit] will show a clear button if [code]text[/code] is not empty, which can be used to clear the text quickly.
</member>
<member name="context_menu_enabled" type="bool" setter="set_context_menu_enabled" getter="is_context_menu_enabled" default="true">
If [code]true[/code], the context menu will appear when right-clicked.
@@ -128,14 +128,21 @@
The character to use to mask secret input (defaults to "*"). Only a single character can be used as the secret character.
</member>
<member name="selecting_enabled" type="bool" setter="set_selecting_enabled" getter="is_selecting_enabled" default="true">
+ If [code]false[/code], it's impossible to select the text using mouse nor keyboard.
</member>
<member name="shortcut_keys_enabled" type="bool" setter="set_shortcut_keys_enabled" getter="is_shortcut_keys_enabled" default="true">
+ If [code]false[/code], using shortcuts will be disabled.
</member>
<member name="text" type="String" setter="set_text" getter="get_text" default="&quot;&quot;">
String value of the [LineEdit].
</member>
</members>
<signals>
+ <signal name="text_change_rejected">
+ <description>
+ Emitted when trying to append text that would overflow the [member max_length].
+ </description>
+ </signal>
<signal name="text_changed">
<argument index="0" name="new_text" type="String">
</argument>
@@ -192,30 +199,43 @@
</constants>
<theme_items>
<theme_item name="clear" type="Texture">
+ Texture for the clear button. See [member clear_button_enabled].
</theme_item>
<theme_item name="clear_button_color" type="Color" default="Color( 0.88, 0.88, 0.88, 1 )">
+ Color used as default tint for the clear button.
</theme_item>
<theme_item name="clear_button_color_pressed" type="Color" default="Color( 1, 1, 1, 1 )">
+ Color used for the clear button when it's pressed.
</theme_item>
<theme_item name="cursor_color" type="Color" default="Color( 0.94, 0.94, 0.94, 1 )">
+ Color of the [LineEdit]'s visual cursor (caret).
</theme_item>
<theme_item name="focus" type="StyleBox">
+ Background used when [LineEdit] has GUI focus.
</theme_item>
<theme_item name="font" type="Font">
+ Font used for the text.
</theme_item>
<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_color_selected" type="Color" default="Color( 0, 0, 0, 1 )">
+ Font color for selected text (inside the selection rectangle).
</theme_item>
<theme_item name="font_color_uneditable" 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).
</theme_item>
<theme_item name="normal" type="StyleBox">
+ Default background for the [LineEdit].
</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>
<theme_item name="selection_color" type="Color" default="Color( 0.49, 0.49, 0.49, 1 )">
+ Color of the selection rectangle.
</theme_item>
</theme_items>
</class>
diff --git a/doc/classes/MainLoop.xml b/doc/classes/MainLoop.xml
index 9457800825..606c898a35 100644
--- a/doc/classes/MainLoop.xml
+++ b/doc/classes/MainLoop.xml
@@ -69,6 +69,7 @@
<argument index="1" name="meta" type="Variant">
</argument>
<description>
+ Called when the user performs an action in the system global menu (e.g. the Mac OS menu bar).
</description>
</method>
<method name="_idle" qualifiers="virtual">
@@ -174,7 +175,7 @@
<argument index="1" name="granted" type="bool">
</argument>
<description>
- Emitted when an user responds to permission request.
+ Emitted when a user responds to a permission request.
</description>
</signal>
</signals>
diff --git a/doc/classes/Mesh.xml b/doc/classes/Mesh.xml
index d4804930e1..2dd3ce5529 100644
--- a/doc/classes/Mesh.xml
+++ b/doc/classes/Mesh.xml
@@ -103,6 +103,7 @@
</methods>
<members>
<member name="lightmap_size_hint" type="Vector2" setter="set_lightmap_size_hint" getter="get_lightmap_size_hint" default="Vector2( 0, 0 )">
+ Sets a hint to be used for lightmap resolution in [BakedLightmap]. Overrides [member BakedLightmap.bake_default_texels_per_unit].
</member>
</members>
<constants>
@@ -128,52 +129,76 @@
Render array as triangle fans.
</constant>
<constant name="BLEND_SHAPE_MODE_NORMALIZED" value="0" enum="BlendShapeMode">
+ Blend shapes are normalized.
</constant>
<constant name="BLEND_SHAPE_MODE_RELATIVE" value="1" enum="BlendShapeMode">
+ Blend shapes are relative to base weight.
</constant>
<constant name="ARRAY_FORMAT_VERTEX" value="1" enum="ArrayFormat">
+ Mesh array contains vertices. All meshes require a vertex array so this should always be present.
</constant>
<constant name="ARRAY_FORMAT_NORMAL" value="2" enum="ArrayFormat">
+ Mesh array contains normals.
</constant>
<constant name="ARRAY_FORMAT_TANGENT" value="4" enum="ArrayFormat">
+ Mesh array contains tangents.
</constant>
<constant name="ARRAY_FORMAT_COLOR" value="8" enum="ArrayFormat">
+ Mesh array contains colors.
</constant>
<constant name="ARRAY_FORMAT_TEX_UV" value="16" enum="ArrayFormat">
+ Mesh array contains UVs.
</constant>
<constant name="ARRAY_FORMAT_TEX_UV2" value="32" enum="ArrayFormat">
+ Mesh array contains second UV.
</constant>
<constant name="ARRAY_FORMAT_BONES" value="64" enum="ArrayFormat">
+ Mesh array contains bones.
</constant>
<constant name="ARRAY_FORMAT_WEIGHTS" value="128" enum="ArrayFormat">
+ Mesh array contains bone weights.
</constant>
<constant name="ARRAY_FORMAT_INDEX" value="256" enum="ArrayFormat">
+ Mesh array uses indices.
</constant>
<constant name="ARRAY_COMPRESS_BASE" value="9" enum="ArrayFormat">
+ Used internally to calculate other [code]ARRAY_COMPRESS_*[/code] enum values. Do not use.
</constant>
<constant name="ARRAY_COMPRESS_VERTEX" value="512" enum="ArrayFormat">
+ Flag used to mark a compressed (half float) vertex array.
</constant>
<constant name="ARRAY_COMPRESS_NORMAL" value="1024" enum="ArrayFormat">
+ Flag used to mark a compressed (half float) normal array.
</constant>
<constant name="ARRAY_COMPRESS_TANGENT" value="2048" enum="ArrayFormat">
+ Flag used to mark a compressed (half float) tangent array.
</constant>
<constant name="ARRAY_COMPRESS_COLOR" value="4096" enum="ArrayFormat">
+ Flag used to mark a compressed (half float) color array.
</constant>
<constant name="ARRAY_COMPRESS_TEX_UV" value="8192" enum="ArrayFormat">
+ Flag used to mark a compressed (half float) UV coordinates array.
</constant>
<constant name="ARRAY_COMPRESS_TEX_UV2" value="16384" enum="ArrayFormat">
+ Flag used to mark a compressed (half float) UV coordinates array for the second UV coordinates.
</constant>
<constant name="ARRAY_COMPRESS_BONES" value="32768" enum="ArrayFormat">
+ Flag used to mark a compressed bone array.
</constant>
<constant name="ARRAY_COMPRESS_WEIGHTS" value="65536" enum="ArrayFormat">
+ Flag used to mark a compressed (half float) weight array.
</constant>
<constant name="ARRAY_COMPRESS_INDEX" value="131072" enum="ArrayFormat">
+ Flag used to mark a compressed index array.
</constant>
<constant name="ARRAY_FLAG_USE_2D_VERTICES" value="262144" enum="ArrayFormat">
+ Flag used to mark that the array contains 2D vertices.
</constant>
<constant name="ARRAY_FLAG_USE_16_BIT_BONES" value="524288" enum="ArrayFormat">
+ Flag used to mark that the array uses 16-bit bones instead of 8-bit.
</constant>
<constant name="ARRAY_COMPRESS_DEFAULT" value="97280" enum="ArrayFormat">
+ Used to set flags [constant ARRAY_COMPRESS_VERTEX], [constant ARRAY_COMPRESS_NORMAL], [constant ARRAY_COMPRESS_TANGENT], [constant ARRAY_COMPRESS_COLOR], [constant ARRAY_COMPRESS_TEX_UV], [constant ARRAY_COMPRESS_TEX_UV2] and [constant ARRAY_COMPRESS_WEIGHTS] quickly.
</constant>
<constant name="ARRAY_VERTEX" value="0" enum="ArrayType">
Array of vertices.
diff --git a/doc/classes/MeshInstance.xml b/doc/classes/MeshInstance.xml
index a4d2bb4295..c7cddf5977 100644
--- a/doc/classes/MeshInstance.xml
+++ b/doc/classes/MeshInstance.xml
@@ -66,6 +66,7 @@
[NodePath] to the [Skeleton] associated with the instance.
</member>
<member name="skin" type="Skin" setter="set_skin" getter="get_skin">
+ Sets the skin to be used by this instance.
</member>
</members>
<constants>
diff --git a/doc/classes/MeshInstance2D.xml b/doc/classes/MeshInstance2D.xml
index 4b38b9aa96..7f1466ccf6 100644
--- a/doc/classes/MeshInstance2D.xml
+++ b/doc/classes/MeshInstance2D.xml
@@ -25,6 +25,7 @@
<signals>
<signal name="texture_changed">
<description>
+ Emitted when the [member texture] is changed.
</description>
</signal>
</signals>
diff --git a/doc/classes/MultiMesh.xml b/doc/classes/MultiMesh.xml
index 8a72aa155b..ec65f407cd 100644
--- a/doc/classes/MultiMesh.xml
+++ b/doc/classes/MultiMesh.xml
@@ -11,6 +11,7 @@
</description>
<tutorials>
<link>http://docs.godotengine.org/en/latest/tutorials/3d/vertex_animation/animating_thousands_of_fish.html</link>
+ <link>http://docs.godotengine.org/en/latest/tutorials/optimization/using_multimesh.html</link>
</tutorials>
<methods>
<method name="get_aabb" qualifiers="const">
@@ -87,7 +88,7 @@
<argument index="1" name="custom_data" type="Color">
</argument>
<description>
- Sets custom data for a specific instance. Although [Color] is used, it is just a container for 4 numbers.
+ Sets custom data for a specific instance. Although [Color] is used, it is just a container for 4 floating point numbers. The format of the number can change depending on the [enum CustomDataFormat] used.
</description>
</method>
<method name="set_instance_transform">
@@ -153,7 +154,7 @@
Use when you are not using per-instance custom data.
</constant>
<constant name="CUSTOM_DATA_8BIT" value="1" enum="CustomDataFormat">
- Compress custom_data into 8 bits when passing to shader. This uses less memory and can be faster, but loses precision.
+ Compress custom_data into 8 bits when passing to shader. This uses less memory and can be faster, but loses precision and range. Floats packed into 8 bits can only represent values between 0 and 1, numbers outside that range will be clamped.
</constant>
<constant name="CUSTOM_DATA_FLOAT" value="2" enum="CustomDataFormat">
The [Color] passed into [method set_instance_custom_data] will use 4 floats. Use this for highest precision.
diff --git a/doc/classes/MultiMeshInstance.xml b/doc/classes/MultiMeshInstance.xml
index 16f16fdc8b..7dcfd2808d 100644
--- a/doc/classes/MultiMeshInstance.xml
+++ b/doc/classes/MultiMeshInstance.xml
@@ -10,6 +10,7 @@
<tutorials>
<link>http://docs.godotengine.org/en/latest/tutorials/3d/vertex_animation/animating_thousands_of_fish.html</link>
<link>http://docs.godotengine.org/en/latest/tutorials/3d/using_multi_mesh_instance.html</link>
+ <link>http://docs.godotengine.org/en/latest/tutorials/optimization/using_multimesh.html</link>
</tutorials>
<methods>
</methods>
diff --git a/doc/classes/MultiMeshInstance2D.xml b/doc/classes/MultiMeshInstance2D.xml
index 8509986c3c..0c6f1a4a62 100644
--- a/doc/classes/MultiMeshInstance2D.xml
+++ b/doc/classes/MultiMeshInstance2D.xml
@@ -25,6 +25,7 @@
<signals>
<signal name="texture_changed">
<description>
+ Emitted when the [member texture] is changed.
</description>
</signal>
</signals>
diff --git a/doc/classes/NinePatchRect.xml b/doc/classes/NinePatchRect.xml
index 221a3c22c1..7a7973684d 100644
--- a/doc/classes/NinePatchRect.xml
+++ b/doc/classes/NinePatchRect.xml
@@ -15,6 +15,7 @@
<argument index="0" name="margin" type="int" enum="Margin">
</argument>
<description>
+ Returns the size of the margin identified by the given [enum Margin] constant.
</description>
</method>
<method name="set_patch_margin">
@@ -25,6 +26,7 @@
<argument index="1" name="value" type="int">
</argument>
<description>
+ Sets the size of the margin identified by the given [enum Margin] constant to [code]value[/code] in pixels.
</description>
</method>
</methods>
@@ -61,7 +63,7 @@
<signals>
<signal name="texture_changed">
<description>
- Fired when the node's texture changes.
+ Emitted when the node's texture changes.
</description>
</signal>
</signals>
diff --git a/doc/classes/OS.xml b/doc/classes/OS.xml
index 22f4dc2d83..2c44a3dfb0 100644
--- a/doc/classes/OS.xml
+++ b/doc/classes/OS.xml
@@ -613,9 +613,9 @@
<return type="bool">
</return>
<description>
- Returns [code]true[/code] if the build is a debug build.
- Returns [code]true[/code] when running in the editor.
- Returns [code]false[/code] if the build is a release build.
+ Returns [code]true[/code] if the Godot binary used to run the project is a [i]debug[/i] export template, or when running in the editor.
+ Returns [code]false[/code] if the Godot binary used to run the project is a [i]release[/i] export template.
+ To check whether the Godot binary used to run the project is an export template (debug or release), use [code]OS.has_feature("standalone")[/code] instead.
</description>
</method>
<method name="is_ok_left_and_cancel_right" qualifiers="const">
@@ -655,6 +655,14 @@
Returns [code]true[/code] if the window should always be on top of other windows.
</description>
</method>
+ <method name="is_window_focused" qualifiers="const">
+ <return type="bool">
+ </return>
+ <description>
+ Returns [code]true[/code] if the window is currently focused.
+ [b]Note:[/b] Only implemented on desktop platforms. On other platforms, it will always return [code]true[/code].
+ </description>
+ </method>
<method name="kill">
<return type="int" enum="Error">
</return>
@@ -931,6 +939,8 @@
</member>
<member name="vsync_via_compositor" type="bool" setter="set_vsync_via_compositor" getter="is_vsync_via_compositor_enabled" default="false">
If [code]true[/code] and [code]vsync_enabled[/code] is true, the operating system's window compositor will be used for vsync when the compositor is enabled and the game is in windowed mode.
+ [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.
+ [b]Note:[/b] This property is only implemented on Windows.
</member>
<member name="window_borderless" type="bool" setter="set_borderless_window" getter="get_borderless_window" default="false">
If [code]true[/code], removes the window frame.
diff --git a/doc/classes/Object.xml b/doc/classes/Object.xml
index 1d7e5f8080..d063bd81e7 100644
--- a/doc/classes/Object.xml
+++ b/doc/classes/Object.xml
@@ -203,7 +203,7 @@
<argument index="0" name="property" type="String">
</argument>
<description>
- Returns the [Variant] value of the given [code]property[/code].
+ Returns the [Variant] value of the given [code]property[/code]. If the [code]property[/code] doesn't exist, this will return [code]null[/code].
</description>
</method>
<method name="get_class" qualifiers="const">
@@ -460,6 +460,7 @@
</argument>
<description>
Assigns a script to the object. Each object can have a single script assigned to it, which are used to extend its functionality.
+ If the object already had a script, the previous script instance will be freed and its variables and state will be lost. The new script's [method _init] method will be called.
</description>
</method>
<method name="to_string">
diff --git a/doc/classes/OmniLight.xml b/doc/classes/OmniLight.xml
index 7189826385..646c2d3166 100644
--- a/doc/classes/OmniLight.xml
+++ b/doc/classes/OmniLight.xml
@@ -33,8 +33,10 @@
Shadows are rendered to a cubemap. Slower than [constant SHADOW_DUAL_PARABOLOID], but higher-quality.
</constant>
<constant name="SHADOW_DETAIL_VERTICAL" value="0" enum="ShadowDetail">
+ Use more detail vertically when computing the shadow.
</constant>
<constant name="SHADOW_DETAIL_HORIZONTAL" value="1" enum="ShadowDetail">
+ Use more detail horizontally when computing the shadow.
</constant>
</constants>
</class>
diff --git a/doc/classes/ParticlesMaterial.xml b/doc/classes/ParticlesMaterial.xml
index 187ad1688d..1f23649b75 100644
--- a/doc/classes/ParticlesMaterial.xml
+++ b/doc/classes/ParticlesMaterial.xml
@@ -321,5 +321,8 @@
<constant name="EMISSION_SHAPE_DIRECTED_POINTS" value="4" enum="EmissionShape">
Particles will be emitted at a position determined by sampling a random point on the [member emission_point_texture]. Particle velocity and rotation will be set based on [member emission_normal_texture]. Particle color will be modulated by [member emission_color_texture].
</constant>
+ <constant name="EMISSION_SHAPE_MAX" value="5" enum="EmissionShape">
+ Represents the size of the [enum EmissionShape] enum.
+ </constant>
</constants>
</class>
diff --git a/doc/classes/PoolByteArray.xml b/doc/classes/PoolByteArray.xml
index 867f042cd2..83c348f6be 100644
--- a/doc/classes/PoolByteArray.xml
+++ b/doc/classes/PoolByteArray.xml
@@ -78,6 +78,11 @@
<return type="String">
</return>
<description>
+ Returns a hexadecimal representation of this array as a [String].
+ [codeblock]
+ var array = PoolByteArray([11, 46, 255])
+ print(array.hex_encode()) # Prints: 0b2eff
+ [/codeblock]
</description>
</method>
<method name="insert">
diff --git a/doc/classes/PopupMenu.xml b/doc/classes/PopupMenu.xml
index c920b52df6..89039eebda 100644
--- a/doc/classes/PopupMenu.xml
+++ b/doc/classes/PopupMenu.xml
@@ -521,6 +521,7 @@
<argument index="1" name="state" type="int">
</argument>
<description>
+ Sets the state of an multistate item. See [method add_multistate_item] for details.
</description>
</method>
<method name="set_item_shortcut">
@@ -595,6 +596,7 @@
<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.
</description>
</method>
</methods>
diff --git a/doc/classes/ProjectSettings.xml b/doc/classes/ProjectSettings.xml
index 126f11a4ed..221214409f 100644
--- a/doc/classes/ProjectSettings.xml
+++ b/doc/classes/ProjectSettings.xml
@@ -321,6 +321,9 @@
<member name="debug/gdscript/warnings/standalone_expression" type="bool" setter="" getter="" default="true">
If [code]true[/code], enables warnings when calling an expression that has no effect on the surrounding code, such as writing [code]2 + 2[/code] as a statement.
</member>
+ <member name="debug/gdscript/warnings/standalone_ternary" type="bool" setter="" getter="" default="true">
+ If [code]true[/code], enables warnings when calling a ternary expression that has no effect on the surrounding code, such as writing [code]42 if active else 0[/code] as a statement.
+ </member>
<member name="debug/gdscript/warnings/treat_warnings_as_errors" type="bool" setter="" getter="" default="false">
If [code]true[/code], all warnings will be reported as if they were errors.
</member>
@@ -439,6 +442,7 @@
</member>
<member name="display/window/vsync/vsync_via_compositor" type="bool" setter="" getter="" default="false">
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;">
</member>
diff --git a/doc/classes/RichTextLabel.xml b/doc/classes/RichTextLabel.xml
index 2567b64c03..c3fb226b6a 100644
--- a/doc/classes/RichTextLabel.xml
+++ b/doc/classes/RichTextLabel.xml
@@ -91,6 +91,7 @@
<argument index="0" name="effect" type="Variant">
</argument>
<description>
+ Installs a custom effect. [code]effect[/code] should be a valid [RichTextEffect].
</description>
</method>
<method name="newline">
@@ -115,6 +116,7 @@
<argument index="0" name="expressions" type="PoolStringArray">
</argument>
<description>
+ Parses BBCode parameter [code]expressions[/code] into a dictionary.
</description>
</method>
<method name="pop">
@@ -137,12 +139,14 @@
<return type="void">
</return>
<description>
+ Adds a [code][font][/code] tag with a bold font to the tag stack. This is the same as adding a [code][b][/code] tag if not currently in a [code][i][/code] tag.
</description>
</method>
<method name="push_bold_italics">
<return type="void">
</return>
<description>
+ Adds a [code][font][/code] tag with a bold italics font to the tag stack.
</description>
</method>
<method name="push_cell">
@@ -176,13 +180,14 @@
<argument index="0" name="level" type="int">
</argument>
<description>
- Adds an [code][indent][/code] tag to the tag stack. Multiplies "level" by current tab_size to determine new margin length.
+ Adds an [code][indent][/code] tag to the tag stack. Multiplies [code]level[/code] by current [member tab_size] to determine new margin length.
</description>
</method>
<method name="push_italics">
<return type="void">
</return>
<description>
+ Adds a [code][font][/code] tag with a italics font to the tag stack. This is the same as adding a [code][i][/code] tag if not currently in a [code][b][/code] tag.
</description>
</method>
<method name="push_list">
@@ -207,12 +212,14 @@
<return type="void">
</return>
<description>
+ Adds a [code][font][/code] tag with a monospace font to the tag stack.
</description>
</method>
<method name="push_normal">
<return type="void">
</return>
<description>
+ Adds a [code][font][/code] tag with a normal font to the tag stack.
</description>
</method>
<method name="push_strikethrough">
@@ -245,6 +252,7 @@
</argument>
<description>
Removes a line of content from the label. Returns [code]true[/code] if the line exists.
+ The [code]line[/code] argument is the index of the line to remove, it can take values in the interval [code][0, get_line_count() - 1][/code].
</description>
</method>
<method name="scroll_to_line">
@@ -281,6 +289,8 @@
[b]Note:[/b] It is unadvised to use [code]+=[/code] operator with [code]bbcode_text[/code] (e.g. [code]bbcode_text += "some string"[/code]) as it replaces the whole text and can cause slowdowns. Use [method append_bbcode] for adding text instead.
</member>
<member name="custom_effects" type="Array" setter="set_effects" getter="get_effects" default="[ ]">
+ The currently installed custom effects. This is an array of [RichTextEffect]s.
+ To add a custom effect, it's more convenient to use [method install_effect].
</member>
<member name="meta_underlined" type="bool" setter="set_meta_underline" getter="is_meta_underlined" default="true">
If [code]true[/code], the label underlines meta tags such as [code][url]{text}[/url][/code].
@@ -289,11 +299,12 @@
If [code]true[/code], the label uses the custom font color.
</member>
<member name="percent_visible" type="float" setter="set_percent_visible" getter="get_percent_visible" default="1.0">
- The text's visibility, as a [float] between 0.0 and 1.0.
+ The range of characters to display, as a [float] between 0.0 and 1.0. When assigned an out of range value, it's the same as assigning 1.0.
+ [b]Note:[/b] Setting this property updates [member visible_characters] based on current [method get_total_character_count].
</member>
<member name="rect_clip_content" type="bool" setter="set_clip_contents" getter="is_clipping_contents" override="true" default="true" />
<member name="scroll_active" type="bool" setter="set_scroll_active" getter="is_scroll_active" default="true">
- If [code]true[/code], the scrollbar is visible. Does not block scrolling completely. See [method scroll_to_line].
+ If [code]true[/code], the scrollbar is visible. Setting this to [code]false[/code] does not block scrolling completely. See [method scroll_to_line].
</member>
<member name="scroll_following" type="bool" setter="set_scroll_follow" getter="is_scroll_following" default="false">
If [code]true[/code], the window scrolls down to display new content automatically.
@@ -317,7 +328,7 @@
<argument index="0" name="meta" type="Nil">
</argument>
<description>
- Triggered when the user clicks on content between [code][url][/code] tags. If the meta is defined in text, e.g. [code][url={"data"="hi"}]hi[/url][/code], then the parameter for this signal will be a [String] type. If a particular type or an object is desired, the [method push_meta] method must be used to manually insert the data into the tag stack.
+ Triggered when the user clicks on content between meta tags. If the meta is defined in text, e.g. [code][url={"data"="hi"}]hi[/url][/code], then the parameter for this signal will be a [String] type. If a particular type or an object is desired, the [method push_meta] method must be used to manually insert the data into the tag stack.
</description>
</signal>
<signal name="meta_hover_ended">
@@ -337,18 +348,25 @@
</signals>
<constants>
<constant name="ALIGN_LEFT" value="0" enum="Align">
+ Makes text left aligned.
</constant>
<constant name="ALIGN_CENTER" value="1" enum="Align">
+ Makes text centered.
</constant>
<constant name="ALIGN_RIGHT" value="2" enum="Align">
+ Makes text right aligned.
</constant>
<constant name="ALIGN_FILL" value="3" enum="Align">
+ Makes text fill width.
</constant>
<constant name="LIST_NUMBERS" value="0" enum="ListType">
+ Each list item has a number marker.
</constant>
<constant name="LIST_LETTERS" value="1" enum="ListType">
+ Each list item has a letter marker.
</constant>
<constant name="LIST_DOTS" value="2" enum="ListType">
+ Each list item has a filled circle marker.
</constant>
<constant name="ITEM_FRAME" value="0" enum="ItemType">
</constant>
diff --git a/doc/classes/ScriptCreateDialog.xml b/doc/classes/ScriptCreateDialog.xml
index 3d0fa9a0d5..2991d76bec 100644
--- a/doc/classes/ScriptCreateDialog.xml
+++ b/doc/classes/ScriptCreateDialog.xml
@@ -24,6 +24,8 @@
</argument>
<argument index="2" name="built_in_enabled" type="bool" default="true">
</argument>
+ <argument index="3" name="load_enabled" type="bool" default="true">
+ </argument>
<description>
Prefills required fields to configure the ScriptCreateDialog for use.
</description>
diff --git a/doc/classes/ScrollBar.xml b/doc/classes/ScrollBar.xml
index ea30b9d48c..e4ace8e8ae 100644
--- a/doc/classes/ScrollBar.xml
+++ b/doc/classes/ScrollBar.xml
@@ -12,6 +12,7 @@
</methods>
<members>
<member name="custom_step" type="float" setter="set_custom_step" getter="get_custom_step" default="-1.0">
+ Overrides the step used when clicking increment and decrement buttons or when using arrow keys when the [ScrollBar] is focused.
</member>
<member name="size_flags_vertical" type="int" setter="set_v_size_flags" getter="get_v_size_flags" override="true" default="0" />
<member name="step" type="float" setter="set_step" getter="get_step" override="true" default="0.0" />
diff --git a/doc/classes/ShaderMaterial.xml b/doc/classes/ShaderMaterial.xml
index ef355c4417..0f39b703ca 100644
--- a/doc/classes/ShaderMaterial.xml
+++ b/doc/classes/ShaderMaterial.xml
@@ -25,6 +25,7 @@
<argument index="0" name="name" type="String">
</argument>
<description>
+ Returns [code]true[/code] if the property identified by [code]name[/code] can be reverted to a default value.
</description>
</method>
<method name="property_get_revert">
@@ -33,6 +34,7 @@
<argument index="0" name="name" type="String">
</argument>
<description>
+ Returns the default value of the material property with given [code]name[/code].
</description>
</method>
<method name="set_shader_param">
diff --git a/doc/classes/SpinBox.xml b/doc/classes/SpinBox.xml
index bda0b1192d..dfa14fc512 100644
--- a/doc/classes/SpinBox.xml
+++ b/doc/classes/SpinBox.xml
@@ -19,6 +19,13 @@
<tutorials>
</tutorials>
<methods>
+ <method name="apply">
+ <return type="void">
+ </return>
+ <description>
+ Applies the current value of this [SpinBox].
+ </description>
+ </method>
<method name="get_line_edit">
<return type="LineEdit">
</return>
diff --git a/doc/classes/SplitContainer.xml b/doc/classes/SplitContainer.xml
index 71731f685a..25d4546c3a 100644
--- a/doc/classes/SplitContainer.xml
+++ b/doc/classes/SplitContainer.xml
@@ -4,7 +4,7 @@
Container for splitting and adjusting.
</brief_description>
<description>
- Container for splitting two controls vertically or horizontally, with a grabber that allows adjusting the split offset or ratio.
+ Container for splitting two [Control]s vertically or horizontally, with a grabber that allows adjusting the split offset or ratio.
</description>
<tutorials>
</tutorials>
@@ -13,16 +13,19 @@
<return type="void">
</return>
<description>
+ Clamps the [member split_offset] value to not go outside the currently possible minimal and maximum values.
</description>
</method>
</methods>
<members>
<member name="collapsed" type="bool" setter="set_collapsed" getter="is_collapsed" default="false">
+ If [code]true[/code], the area of the first [Control] will be collapsed and the dragger will be disabled.
</member>
<member name="dragger_visibility" type="int" setter="set_dragger_visibility" getter="get_dragger_visibility" enum="SplitContainer.DraggerVisibility" default="0">
- Determines the dragger's visibility. See [enum DraggerVisibility] for options.
+ Determines the dragger's visibility. See [enum DraggerVisibility] for details.
</member>
<member name="split_offset" type="int" setter="set_split_offset" getter="get_split_offset" default="0">
+ The initial offset of the splitting between the two [Control]s, with [code]0[/code] being at the end of the first [Control].
</member>
</members>
<signals>
@@ -36,13 +39,13 @@
</signals>
<constants>
<constant name="DRAGGER_VISIBLE" value="0" enum="DraggerVisibility">
- The split dragger is visible.
+ The split dragger is visible when the cursor hovers it.
</constant>
<constant name="DRAGGER_HIDDEN" value="1" enum="DraggerVisibility">
- The split dragger is invisible.
+ The split dragger is never visible.
</constant>
<constant name="DRAGGER_HIDDEN_COLLAPSED" value="2" enum="DraggerVisibility">
- The split dragger is invisible and collapsed.
+ The split dragger is never visible and its space collapsed.
</constant>
</constants>
</class>
diff --git a/doc/classes/SpriteFrames.xml b/doc/classes/SpriteFrames.xml
index f28192519e..2f2075074c 100644
--- a/doc/classes/SpriteFrames.xml
+++ b/doc/classes/SpriteFrames.xml
@@ -170,6 +170,7 @@
</methods>
<members>
<member name="frames" type="Array" setter="_set_frames" getter="_get_frames">
+ Compatibility property, always equals to an empty array.
</member>
</members>
<constants>
diff --git a/doc/classes/StreamPeerSSL.xml b/doc/classes/StreamPeerSSL.xml
index b34d8d1b25..eea44ef93d 100644
--- a/doc/classes/StreamPeerSSL.xml
+++ b/doc/classes/StreamPeerSSL.xml
@@ -38,6 +38,7 @@
</argument>
<description>
Connects to a peer using an underlying [StreamPeer] [code]stream[/code]. If [code]validate_certs[/code] is [code]true[/code], [StreamPeerSSL] will validate that the certificate presented by the peer matches the [code]for_hostname[/code].
+ [b]Note:[/b] Specifying a custom [code]valid_certificate[/code] is not supported in HTML5 exports due to browsers restrictions.
</description>
</method>
<method name="disconnect_from_stream">
diff --git a/doc/classes/StyleBox.xml b/doc/classes/StyleBox.xml
index 1d873ef0b1..1a11904792 100644
--- a/doc/classes/StyleBox.xml
+++ b/doc/classes/StyleBox.xml
@@ -17,18 +17,22 @@
<argument index="1" name="rect" type="Rect2">
</argument>
<description>
+ Draws this stylebox using a [CanvasItem] with given [RID].
+ You can get a [RID] value using [method Object.get_instance_id] on a [CanvasItem]-derived node.
</description>
</method>
<method name="get_center_size" qualifiers="const">
<return type="Vector2">
</return>
<description>
+ Returns the size of this [StyleBox] without the margins.
</description>
</method>
<method name="get_current_item_drawn" qualifiers="const">
<return type="CanvasItem">
</return>
<description>
+ Returns the [CanvasItem] that handles its [constant CanvasItem.NOTIFICATION_DRAW] or [method CanvasItem._draw] callback at this moment.
</description>
</method>
<method name="get_default_margin" qualifiers="const">
@@ -37,6 +41,7 @@
<argument index="0" name="margin" type="int" enum="Margin">
</argument>
<description>
+ Returns the default value of the specified [enum Margin].
</description>
</method>
<method name="get_margin" qualifiers="const">
@@ -45,7 +50,7 @@
<argument index="0" name="margin" type="int" enum="Margin">
</argument>
<description>
- Returns the content margin offset for the specified margin.
+ Returns the content margin offset for the specified [enum Margin].
Positive values reduce size inwards, unlike [Control]'s margin values.
</description>
</method>
@@ -71,6 +76,7 @@
<argument index="1" name="offset" type="float">
</argument>
<description>
+ Sets the default value of the specified [enum Margin] to given [code]offset[/code] in pixels.
</description>
</method>
<method name="test_mask" qualifiers="const">
diff --git a/doc/classes/TabContainer.xml b/doc/classes/TabContainer.xml
index 1f584ad317..e5f126c344 100644
--- a/doc/classes/TabContainer.xml
+++ b/doc/classes/TabContainer.xml
@@ -150,6 +150,7 @@
If [code]true[/code], tabs are visible. If [code]false[/code], tabs' content and titles are hidden.
</member>
<member name="use_hidden_tabs_for_min_size" type="bool" setter="set_use_hidden_tabs_for_min_size" getter="get_use_hidden_tabs_for_min_size" default="false">
+ If [code]true[/code], children [Control] nodes that are hidden have their minimum size take into account in the total, instead of only the currently visible one.
</member>
</members>
<signals>
diff --git a/doc/classes/Tabs.xml b/doc/classes/Tabs.xml
index 6bd7b8c2c3..04119b7cdb 100644
--- a/doc/classes/Tabs.xml
+++ b/doc/classes/Tabs.xml
@@ -33,6 +33,7 @@
<return type="bool">
</return>
<description>
+ Returns [code]true[/code] if the offset buttons (the ones that appear when there's not enough space for all tabs) are visible.
</description>
</method>
<method name="get_select_with_rmb" qualifiers="const">
@@ -71,6 +72,7 @@
<return type="int">
</return>
<description>
+ Returns the number of hidden tabs offsetted to the left.
</description>
</method>
<method name="get_tab_rect" qualifiers="const">
@@ -179,11 +181,13 @@
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.
</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 [code]TabAlign[/code] constants for details.
+ The alignment of all tabs. See [enum TabAlign] for details.
</member>
<member name="tab_close_display_policy" type="int" setter="set_tab_close_display_policy" getter="get_tab_close_display_policy" enum="Tabs.CloseButtonDisplayPolicy" default="0">
+ Sets when the close button will appear on the tabs. See [enum CloseButtonDisplayPolicy] for details.
</member>
</members>
<signals>
@@ -191,36 +195,42 @@
<argument index="0" name="idx_to" type="int">
</argument>
<description>
+ Emitted when the active tab is rearranged via mouse drag. See [member drag_to_rearrange_enabled].
</description>
</signal>
<signal name="right_button_pressed">
<argument index="0" name="tab" type="int">
</argument>
<description>
+ Emitted when a tab is right-clicked.
</description>
</signal>
<signal name="tab_changed">
<argument index="0" name="tab" type="int">
</argument>
<description>
+ Emitted when switching to another tab.
</description>
</signal>
<signal name="tab_clicked">
<argument index="0" name="tab" type="int">
</argument>
<description>
+ Emitted when a tab is clicked, even if it is the current tab.
</description>
</signal>
<signal name="tab_close">
<argument index="0" name="tab" type="int">
</argument>
<description>
+ Emitted when a tab is closed.
</description>
</signal>
<signal name="tab_hover">
<argument index="0" name="tab" type="int">
</argument>
<description>
+ Emitted when a tab is hovered by the mouse.
</description>
</signal>
</signals>
@@ -238,10 +248,13 @@
Represents the size of the [enum TabAlign] enum.
</constant>
<constant name="CLOSE_BUTTON_SHOW_NEVER" value="0" enum="CloseButtonDisplayPolicy">
+ Never show the close buttons.
</constant>
<constant name="CLOSE_BUTTON_SHOW_ACTIVE_ONLY" value="1" enum="CloseButtonDisplayPolicy">
+ Only show the close button on the currently active tab.
</constant>
<constant name="CLOSE_BUTTON_SHOW_ALWAYS" value="2" enum="CloseButtonDisplayPolicy">
+ Show the close button on all tabs.
</constant>
<constant name="CLOSE_BUTTON_MAX" value="3" enum="CloseButtonDisplayPolicy">
Represents the size of the [enum CloseButtonDisplayPolicy] enum.
diff --git a/doc/classes/TextEdit.xml b/doc/classes/TextEdit.xml
index 75fceac500..3deed63ae7 100644
--- a/doc/classes/TextEdit.xml
+++ b/doc/classes/TextEdit.xml
@@ -437,6 +437,12 @@
<member name="readonly" type="bool" setter="set_readonly" getter="is_readonly" default="false">
If [code]true[/code], read-only mode is enabled. Existing text cannot be modified and new text cannot be added.
</member>
+ <member name="scroll_horizontal" type="int" setter="set_h_scroll" getter="get_h_scroll" default="0">
+ The current horizontal scroll value.
+ </member>
+ <member name="scroll_vertical" type="float" setter="set_v_scroll" getter="get_v_scroll" default="0.0">
+ The current vertical scroll value.
+ </member>
<member name="selecting_enabled" type="bool" setter="set_selecting_enabled" getter="is_selecting_enabled" default="true">
</member>
<member name="shortcut_keys_enabled" type="bool" setter="set_shortcut_keys_enabled" getter="is_shortcut_keys_enabled" default="true">
diff --git a/doc/classes/Texture3D.xml b/doc/classes/Texture3D.xml
index c11a48137f..aac55710fe 100644
--- a/doc/classes/Texture3D.xml
+++ b/doc/classes/Texture3D.xml
@@ -1,8 +1,10 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="Texture3D" inherits="TextureLayered" category="Core" version="3.2">
<brief_description>
+ Texture with 3 dimensions.
</brief_description>
<description>
+ Texture3D is a 3-dimensional texture that has a width, height, and depth.
</description>
<tutorials>
</tutorials>
diff --git a/doc/classes/Thread.xml b/doc/classes/Thread.xml
index 25e40d4c1f..e56ea2325e 100644
--- a/doc/classes/Thread.xml
+++ b/doc/classes/Thread.xml
@@ -50,10 +50,13 @@
</methods>
<constants>
<constant name="PRIORITY_LOW" value="0" enum="Priority">
+ A thread running with lower priority than normally.
</constant>
<constant name="PRIORITY_NORMAL" value="1" enum="Priority">
+ A thread with a standard priority.
</constant>
<constant name="PRIORITY_HIGH" value="2" enum="Priority">
+ A thread running with higher priority than normally.
</constant>
</constants>
</class>
diff --git a/doc/classes/Tree.xml b/doc/classes/Tree.xml
index dd4330b00b..aa1f8638d2 100644
--- a/doc/classes/Tree.xml
+++ b/doc/classes/Tree.xml
@@ -43,14 +43,18 @@
<argument index="1" name="idx" type="int" default="-1">
</argument>
<description>
- Create an item in the tree and add it as the last child of [code]parent[/code]. If [code]parent[/code] is [code]null[/code], it will be added as the root's last child, or it'll be the the root itself if the tree is empty.
+ Creates an item in the tree and adds it as a child of [code]parent[/code].
+ If [code]parent[/code] is [code]null[/code], the root item will be the parent, or the new item will be the root itself if the tree is empty.
+ 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="ensure_cursor_is_visible">
<return type="void">
</return>
<description>
- Makes the currently selected item visible. This will scroll the tree to make sure the selected item is visible.
+ Makes the currently focused cell visible.
+ This will scroll the tree if necessary. In [constant SELECT_ROW] mode, this will not do horizontal scrolling, as all the cells in the selected row is focused logically.
+ [b]Note:[/b] Despite the name of this method, the focus cursor itself is only visible in [constant SELECT_MULTI] mode.
</description>
</method>
<method name="get_column_at_position" qualifiers="const">
@@ -59,7 +63,7 @@
<argument index="0" name="position" type="Vector2">
</argument>
<description>
- Returns the column index under the given point.
+ Returns the column index at [code]position[/code], or -1 if no item is there.
</description>
</method>
<method name="get_column_title" qualifiers="const">
@@ -93,8 +97,9 @@
<argument index="0" name="position" type="Vector2">
</argument>
<description>
- If [member drop_mode_flags] includes [constant DROP_MODE_INBETWEEN], returns -1 if [code]position[/code] is the upper part of a tree item at that position, 1 for the lower part, and additionally 0 for the middle part if [member drop_mode_flags] includes [constant DROP_MODE_ON_ITEM].
- Otherwise, returns 0. If there are no tree items at [code]position[/code], returns -100.
+ Returns the drop section at [code]position[/code], or -100 if no item is there.
+ Values -1, 0, or 1 will be returned for the "above item", "on item", and "below item" drop sections, respectively. See [enum DropModeFlags] for a description of each drop section.
+ To get the item which the returned drop section is relative to, use [method get_item_at_position].
</description>
</method>
<method name="get_edited" qualifiers="const">
@@ -119,7 +124,7 @@
<argument index="1" name="column" type="int" default="-1">
</argument>
<description>
- Returns the rectangle area for the specified item. If column is specified, only get the position and size of that column, otherwise get the rectangle containing all columns.
+ Returns the rectangle area for the specified item. If [code]column[/code] is specified, only get the position and size of that column, otherwise get the rectangle containing all columns.
</description>
</method>
<method name="get_item_at_position" qualifiers="const">
@@ -137,7 +142,8 @@
<argument index="0" name="from" type="Object">
</argument>
<description>
- Returns the next selected item after the given one.
+ Returns the next selected item after the given one, or [code]null[/code] if the end is reached.
+ If [code]from[/code] is [code]null[/code], this returns the first selected item.
</description>
</method>
<method name="get_pressed_button" qualifiers="const">
@@ -151,7 +157,7 @@
<return type="TreeItem">
</return>
<description>
- Returns the tree's root item.
+ Returns the tree's root item, or [code]null[/code] if the tree is empty.
</description>
</method>
<method name="get_scroll" qualifiers="const">
@@ -165,14 +171,18 @@
<return type="TreeItem">
</return>
<description>
- Returns the currently selected item.
+ Returns the currently focused item, or [code]null[/code] if no item is focused.
+ In [constant SELECT_ROW] and [constant SELECT_SINGLE] modes, the focused item is same as the selected item. In [constant SELECT_MULTI] mode, the focused item is the item under the focus cursor, not necessarily selected.
+ To get the currently selected item(s), use [method get_next_selected].
</description>
</method>
<method name="get_selected_column" qualifiers="const">
<return type="int">
</return>
<description>
- Returns the current selection's column.
+ Returns the currently focused column, or -1 if no column is focused.
+ In [constant SELECT_SINGLE] mode, the focused column is the selected column. In [constant SELECT_ROW] mode, the focused column is always 0 if any item is selected. In [constant SELECT_MULTI] mode, the focused column is the column under the focus cursor, and there are not necessarily any column selected.
+ To tell whether a column of an item is selected, use [method TreeItem.is_selected].
</description>
</method>
<method name="set_column_expand">
@@ -230,6 +240,7 @@
</member>
<member name="drop_mode_flags" type="int" setter="set_drop_mode_flags" getter="get_drop_mode_flags" default="0">
The drop mode as an OR combination of flags. See [enum DropModeFlags] constants. Once dropping is done, reverts to [constant DROP_MODE_DISABLED]. Setting this during [method Control.can_drop_data] is recommended.
+ This controls the drop sections, i.e. the decision and drawing of possible drop locations based on the mouse position.
</member>
<member name="focus_mode" type="int" setter="set_focus_mode" getter="get_focus_mode" override="true" enum="Control.FocusMode" default="2" />
<member name="hide_folding" type="bool" setter="set_hide_folding" getter="is_folding_hidden" default="false">
@@ -278,6 +289,7 @@
<argument index="0" name="position" type="Vector2">
</argument>
<description>
+ Emitted when the right mouse button is pressed in the empty space of the tree.
</description>
</signal>
<signal name="empty_tree_rmb_selected">
@@ -343,23 +355,34 @@
</signal>
<signal name="nothing_selected">
<description>
+ Emitted when a left mouse button click does not select any item.
</description>
</signal>
</signals>
<constants>
<constant name="SELECT_SINGLE" value="0" enum="SelectMode">
- Allows selection of a single item at a time.
+ Allows selection of a single cell at a time. From the perspective of items, only a single item is allowed to be selected. And there is only one column selected in the selected item.
+ The focus cursor is always hidden in this mode, but it is positioned at the current selection, making the currently selected item the currently focused item.
</constant>
<constant name="SELECT_ROW" value="1" enum="SelectMode">
+ Allows selection of a single row at a time. From the perspective of items, only a single items is allowed to be selected. And all the columns are selected in the selected item.
+ The focus cursor is always hidden in this mode, but it is positioned at the first column of the current selection, making the currently selected item the currently focused item.
</constant>
<constant name="SELECT_MULTI" value="2" enum="SelectMode">
- Allows selection of multiple items at the same time.
+ Allows selection of multiple cells at the same time. From the perspective of items, multiple items are allowed to be selected. And there can be multiple columns selected in each selected item.
+ The focus cursor is visible in this mode, the item or column under the cursor is not necessarily selected.
</constant>
<constant name="DROP_MODE_DISABLED" value="0" enum="DropModeFlags">
+ Disables all drop sections, but still allows to detect the "on item" drop section by [method get_drop_section_at_position].
+ [b]Note:[/b] This is the default flag, it has no effect when combined with other flags.
</constant>
<constant name="DROP_MODE_ON_ITEM" value="1" enum="DropModeFlags">
+ Enables the "on item" drop section. This drop section covers the entire item.
+ When combined with [constant DROP_MODE_INBETWEEN], this drop section halves the height and stays centered vertically.
</constant>
<constant name="DROP_MODE_INBETWEEN" value="2" enum="DropModeFlags">
+ Enables "above item" and "below item" drop sections. The "above item" drop section covers the top half of the item, and the "below item" drop section covers the bottom half.
+ When combined with [constant DROP_MODE_ON_ITEM], these drop sections halves the height and stays on top / bottom accordingly.
</constant>
</constants>
<theme_items>
diff --git a/doc/classes/VScrollBar.xml b/doc/classes/VScrollBar.xml
index 6240178b82..add695ef2c 100644
--- a/doc/classes/VScrollBar.xml
+++ b/doc/classes/VScrollBar.xml
@@ -1,9 +1,10 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="VScrollBar" inherits="ScrollBar" category="Core" version="3.2">
<brief_description>
- Vertical version of [ScrollBar], which goes from top (min) to bottom (max).
+ Vertical scroll bar.
</brief_description>
<description>
+ Vertical version of [ScrollBar], which goes from top (min) to bottom (max).
</description>
<tutorials>
</tutorials>
@@ -17,22 +18,31 @@
</constants>
<theme_items>
<theme_item name="decrement" type="Texture">
+ Icon used as a button to scroll the [ScrollBar] up. Supports custom step using the [member ScrollBar.custom_step] property.
</theme_item>
<theme_item name="decrement_highlight" type="Texture">
+ Displayed when the mouse cursor hovers over the decrement button.
</theme_item>
<theme_item name="grabber" type="StyleBox">
+ Used as texture for the grabber, the draggable element representing current scroll.
</theme_item>
<theme_item name="grabber_highlight" type="StyleBox">
+ Used when the mouse hovers over the grabber.
</theme_item>
<theme_item name="grabber_pressed" type="StyleBox">
+ Used when the grabber is being dragged.
</theme_item>
<theme_item name="increment" type="Texture">
+ Icon used as a button to scroll the [ScrollBar] down. Supports custom step using the [member ScrollBar.custom_step] property.
</theme_item>
<theme_item name="increment_highlight" type="Texture">
+ Displayed when the mouse cursor hovers over the increment button.
</theme_item>
<theme_item name="scroll" type="StyleBox">
+ Used as background of this [ScrollBar].
</theme_item>
<theme_item name="scroll_focus" type="StyleBox">
+ Used as background when the [ScrollBar] has the GUI focus.
</theme_item>
</theme_items>
</class>
diff --git a/doc/classes/VisibilityEnabler.xml b/doc/classes/VisibilityEnabler.xml
index e3c7d05fce..8636d9c8d2 100644
--- a/doc/classes/VisibilityEnabler.xml
+++ b/doc/classes/VisibilityEnabler.xml
@@ -15,6 +15,7 @@
<argument index="0" name="enabler" type="int" enum="VisibilityEnabler.Enabler">
</argument>
<description>
+ Returns whether the enabler identified by given [enum Enabler] constant is active.
</description>
</method>
<method name="set_enabler">
@@ -25,6 +26,7 @@
<argument index="1" name="enabled" type="bool">
</argument>
<description>
+ Sets active state of the enabler identified by given [enum Enabler] constant.
</description>
</method>
</methods>
diff --git a/doc/classes/VisibilityEnabler2D.xml b/doc/classes/VisibilityEnabler2D.xml
index 96f6a42cdf..095a377ccb 100644
--- a/doc/classes/VisibilityEnabler2D.xml
+++ b/doc/classes/VisibilityEnabler2D.xml
@@ -15,6 +15,7 @@
<argument index="0" name="enabler" type="int" enum="VisibilityEnabler2D.Enabler">
</argument>
<description>
+ Returns whether the enabler identified by given [enum Enabler] constant is active.
</description>
</method>
<method name="set_enabler">
@@ -25,6 +26,7 @@
<argument index="1" name="enabled" type="bool">
</argument>
<description>
+ Sets active state of the enabler identified by given [enum Enabler] constant.
</description>
</method>
</methods>
@@ -65,6 +67,7 @@
This enabler will stop the parent's _physics_process function.
</constant>
<constant name="ENABLER_PAUSE_ANIMATED_SPRITES" value="5" enum="Enabler">
+ This enabler will stop [AnimatedSprite] nodes animations.
</constant>
<constant name="ENABLER_MAX" value="6" enum="Enabler">
Represents the size of the [enum Enabler] enum.
diff --git a/doc/classes/VisualInstance.xml b/doc/classes/VisualInstance.xml
index 7576bf7ad8..692e051674 100644
--- a/doc/classes/VisualInstance.xml
+++ b/doc/classes/VisualInstance.xml
@@ -1,8 +1,10 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="VisualInstance" inherits="Spatial" category="Core" version="3.2">
<brief_description>
+ Parent of all visual 3D nodes.
</brief_description>
<description>
+ The VisualInstance is used to connect a resource to a visual representation. All visual 3D nodes inherit from the VisualInstance. In general, you should not access the VisualInstance properties directly as they are accessed and managed by the nodes that inherit from VisualInstance. VisualInstance is the node representation of the [VisualServer] instance.
</description>
<tutorials>
</tutorials>
@@ -18,12 +20,14 @@
<return type="RID">
</return>
<description>
+ Returns the RID of the resource associated with this VisualInstance. For example, if the Node is a [MeshInstance], this will return the RID of the associated [Mesh].
</description>
</method>
<method name="get_instance" qualifiers="const">
<return type="RID">
</return>
<description>
+ Returns the RID of this instance. This RID is the same as the RID returned by [method VisualServer.instance_create]. This RID is needed if you want to call [VisualServer] functions directly on this VisualInstance.
</description>
</method>
<method name="get_layer_mask_bit" qualifiers="const">
@@ -32,6 +36,7 @@
<argument index="0" name="layer" type="int">
</argument>
<description>
+ Returns [code]true[/code] when the specified layer is enabled in [member layers] and [code]false[/code] otherwise.
</description>
</method>
<method name="get_transformed_aabb" qualifiers="const">
@@ -48,8 +53,7 @@
<argument index="0" name="base" type="RID">
</argument>
<description>
- Sets the base of the VisualInstance, which changes how the engine handles the VisualInstance under the hood.
- It is recommended to only use [method set_base] if you know what you're doing.
+ Sets the resource that is instantiated by this VisualInstance, which changes how the engine handles the VisualInstance under the hood. Equivalent to [method VisualServer.instance_set_base].
</description>
</method>
<method name="set_layer_mask_bit">
@@ -60,6 +64,7 @@
<argument index="1" name="enabled" type="bool">
</argument>
<description>
+ Enables a particular layer in [member layers].
</description>
</method>
</methods>
diff --git a/doc/classes/VisualServer.xml b/doc/classes/VisualServer.xml
index a216d4b7b3..c00710ade9 100644
--- a/doc/classes/VisualServer.xml
+++ b/doc/classes/VisualServer.xml
@@ -6,8 +6,16 @@
<description>
Server for anything visible. The visual server is the API backend for everything visible. The whole scene system mounts on it to display.
The visual server is completely opaque, the internals are entirely implementation specific and cannot be accessed.
+ The visual server can be used to bypass the scene system entirely.
+ 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 visual server from a running game, the scenario can be accessed from the scene tree from any [Spatial] node with [method Spatial.get_world]. Otherwise, a scenario can be created with [method scenario_create].
+ 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>
<tutorials>
+ <link>http://docs.godotengine.org/en/latest/tutorials/optimization/using_servers.html</link>
</tutorials>
<methods>
<method name="black_bars_set_images">
@@ -45,6 +53,7 @@
</return>
<description>
Creates a camera and adds it to the VisualServer. It can be accessed with the RID that is returned. This RID will be used in all [code]camera_*[/code] VisualServer functions.
+ Once finished with your RID, you will want to free the RID using the VisualServer's [method free_rid] static method.
</description>
</method>
<method name="camera_set_cull_mask">
@@ -142,7 +151,8 @@
<return type="RID">
</return>
<description>
- Creates a canvas and returns the assigned [RID].
+ Creates a canvas and returns the assigned [RID]. It can be accessed with the RID that is returned. This RID will be used in all [code]canvas_*[/code] VisualServer functions.
+ Once finished with your RID, you will want to free the RID using the VisualServer's [method free_rid] static method.
</description>
</method>
<method name="canvas_item_add_circle">
@@ -441,7 +451,8 @@
<return type="RID">
</return>
<description>
- Creates a new [CanvasItem] and returns its [RID].
+ Creates a new [CanvasItem] and returns its [RID]. It can be accessed with the RID that is returned. This RID will be used in all [code]canvas_item_*[/code] VisualServer functions.
+ Once finished with your RID, you will want to free the RID using the VisualServer's [method free_rid] static method.
</description>
</method>
<method name="canvas_item_set_clip">
@@ -555,7 +566,7 @@
<argument index="1" name="parent" type="RID">
</argument>
<description>
- Sets the parent for the [CanvasItem].
+ Sets the parent for the [CanvasItem]. The parent can be another canvas item, or it can be the root canvas that is attached to the viewport.
</description>
</method>
<method name="canvas_item_set_self_modulate">
@@ -650,7 +661,8 @@
<return type="RID">
</return>
<description>
- Creates a canvas light.
+ Creates a canvas light and adds it to the VisualServer. It can be accessed with the RID that is returned. This RID will be used in all [code]canvas_light_*[/code] VisualServer functions.
+ Once finished with your RID, you will want to free the RID using the VisualServer's [method free_rid] static method.
</description>
</method>
<method name="canvas_light_occluder_attach_to_canvas">
@@ -668,7 +680,8 @@
<return type="RID">
</return>
<description>
- Creates a light occluder.
+ Creates a light occluder and adds it to the VisualServer. It can be accessed with the RID that is returned. This RID will be used in all [code]canvas_light_ocluder_*[/code] VisualServer functions.
+ Once finished with your RID, you will want to free the RID using the VisualServer's [method free_rid] static method.
</description>
</method>
<method name="canvas_light_occluder_set_enabled">
@@ -932,7 +945,8 @@
<return type="RID">
</return>
<description>
- Creates a new light occluder polygon.
+ Creates a new light occluder polygon and adds it to the VisualServer. It can be accessed with the RID that is returned. This RID will be used in all [code]canvas_occluder_polygon_*[/code] VisualServer functions.
+ Once finished with your RID, you will want to free the RID using the VisualServer's [method free_rid] static method.
</description>
</method>
<method name="canvas_occluder_polygon_set_cull_mode">
@@ -999,6 +1013,8 @@
</return>
<description>
Creates a directional light and adds it to the VisualServer. It can be accessed with the RID that is returned. This RID can be used in most [code]light_*[/code] VisualServer functions.
+ Once finished with your RID, you will want to free the RID using the VisualServer's [method free_rid] static method.
+ To place in a scene, attach this directional light to an instance using [method instance_set_base] using the returned RID.
</description>
</method>
<method name="draw">
@@ -1017,6 +1033,7 @@
</return>
<description>
Creates an environment and adds it to the VisualServer. It can be accessed with the RID that is returned. This RID will be used in all [code]environment_*[/code] VisualServer functions.
+ Once finished with your RID, you will want to free the RID using the VisualServer's [method free_rid] static method.
</description>
</method>
<method name="environment_set_adjustment">
@@ -1388,6 +1405,22 @@
Returns the id of the test texture. Creates one if none exists.
</description>
</method>
+ <method name="get_video_adapter_name" qualifiers="const">
+ <return type="String">
+ </return>
+ <description>
+ Returns the name of the video adapter (e.g. "GeForce GTX 1080/PCIe/SSE2").
+ [b]Note:[/b] When running a headless or server binary, this function returns an empty string.
+ </description>
+ </method>
+ <method name="get_video_adapter_vendor" qualifiers="const">
+ <return type="String">
+ </return>
+ <description>
+ Returns the vendor of the video adapter (e.g. "NVIDIA Corporation").
+ [b]Note:[/b] When running a headless or server binary, this function returns an empty string.
+ </description>
+ </method>
<method name="get_white_texture">
<return type="RID">
</return>
@@ -1399,6 +1432,9 @@
<return type="RID">
</return>
<description>
+ Creates a GI probe and adds it to the VisualServer. It can be accessed with the RID that is returned. This RID will be used in all [code]gi_probe_*[/code] VisualServer functions.
+ Once finished with your RID, you will want to free the RID using the VisualServer's [method free_rid] static method.
+ To place in a scene, attach this GI probe to an instance using [method instance_set_base] using the returned RID.
</description>
</method>
<method name="gi_probe_get_bias" qualifiers="const">
@@ -1407,6 +1443,7 @@
<argument index="0" name="probe" type="RID">
</argument>
<description>
+ Returns the bias value for the GI probe. Bias is used to avoid self occlusion. Equivalent to [member GIProbeData.bias].
</description>
</method>
<method name="gi_probe_get_bounds" qualifiers="const">
@@ -1415,6 +1452,7 @@
<argument index="0" name="probe" type="RID">
</argument>
<description>
+ Returns the axis-aligned bounding box that covers the full extent of the GI probe.
</description>
</method>
<method name="gi_probe_get_cell_size" qualifiers="const">
@@ -1423,6 +1461,7 @@
<argument index="0" name="probe" type="RID">
</argument>
<description>
+ Returns the cell size set by [method gi_probe_set_cell_size].
</description>
</method>
<method name="gi_probe_get_dynamic_data" qualifiers="const">
@@ -1431,6 +1470,7 @@
<argument index="0" name="probe" type="RID">
</argument>
<description>
+ Returns the data used by the GI probe.
</description>
</method>
<method name="gi_probe_get_dynamic_range" qualifiers="const">
@@ -1439,6 +1479,7 @@
<argument index="0" name="probe" type="RID">
</argument>
<description>
+ Returns the dynamic range set for this GI probe. Equivalent to [member GIProbe.dynamic_range].
</description>
</method>
<method name="gi_probe_get_energy" qualifiers="const">
@@ -1447,6 +1488,7 @@
<argument index="0" name="probe" type="RID">
</argument>
<description>
+ Returns the energy multiplier for this GI probe. Equivalent to [member GIProbe.energy].
</description>
</method>
<method name="gi_probe_get_normal_bias" qualifiers="const">
@@ -1455,6 +1497,7 @@
<argument index="0" name="probe" type="RID">
</argument>
<description>
+ Returns the normal bias for this GI probe. Equivalent to [member GIProbe.normal_bias].
</description>
</method>
<method name="gi_probe_get_propagation" qualifiers="const">
@@ -1463,6 +1506,7 @@
<argument index="0" name="probe" type="RID">
</argument>
<description>
+ Returns the propagation value for this GI probe. Equivalent to [member GIProbe.propagation].
</description>
</method>
<method name="gi_probe_get_to_cell_xform" qualifiers="const">
@@ -1471,6 +1515,7 @@
<argument index="0" name="probe" type="RID">
</argument>
<description>
+ Returns the Transform set by [method gi_probe_set_to_cell_xform].
</description>
</method>
<method name="gi_probe_is_compressed" qualifiers="const">
@@ -1479,6 +1524,7 @@
<argument index="0" name="probe" type="RID">
</argument>
<description>
+ Returns [code]true[/code] if the GI probe data associated with this GI probe is compressed. Equivalent to [member GIProbe.compress].
</description>
</method>
<method name="gi_probe_is_interior" qualifiers="const">
@@ -1487,6 +1533,7 @@
<argument index="0" name="probe" type="RID">
</argument>
<description>
+ Returns [code]true[/code] if the GI probe is set to interior, meaning it does not account for sky light. Equivalent to [member GIProbe.interior].
</description>
</method>
<method name="gi_probe_set_bias">
@@ -1497,6 +1544,7 @@
<argument index="1" name="bias" type="float">
</argument>
<description>
+ Sets the bias value to avoid self-occlusion. Equivalent to [member GIProbe.bias].
</description>
</method>
<method name="gi_probe_set_bounds">
@@ -1507,6 +1555,7 @@
<argument index="1" name="bounds" type="AABB">
</argument>
<description>
+ Sets the axis-aligned bounding box that covers the extent of the GI probe.
</description>
</method>
<method name="gi_probe_set_cell_size">
@@ -1517,6 +1566,7 @@
<argument index="1" name="range" type="float">
</argument>
<description>
+ Sets the size of individual cells within the GI probe.
</description>
</method>
<method name="gi_probe_set_compress">
@@ -1527,6 +1577,7 @@
<argument index="1" name="enable" type="bool">
</argument>
<description>
+ Sets the compression setting for the GI probe data. Compressed data will take up less space but may look worse. Equivalent to [member GIProbe.compress].
</description>
</method>
<method name="gi_probe_set_dynamic_data">
@@ -1537,6 +1588,7 @@
<argument index="1" name="data" type="PoolIntArray">
</argument>
<description>
+ Sets the data to be used in the GI probe for lighting calculations. Normally this is created and called internally within the [GIProbe] node. You should not try to set this yourself.
</description>
</method>
<method name="gi_probe_set_dynamic_range">
@@ -1547,6 +1599,7 @@
<argument index="1" name="range" type="int">
</argument>
<description>
+ Sets the dynamic range of the GI probe. Dynamic range sets the limit for how bright lights can be. A smaller range captures greater detail but limits how bright lights can be. Equivalent to [member GIProbe.dynamic_range].
</description>
</method>
<method name="gi_probe_set_energy">
@@ -1557,6 +1610,7 @@
<argument index="1" name="energy" type="float">
</argument>
<description>
+ Sets the energy multiplier for this GI probe. A higher energy makes the indirect light from the GI probe brighter. Equivalent to [member GIProbe.energy].
</description>
</method>
<method name="gi_probe_set_interior">
@@ -1567,6 +1621,7 @@
<argument index="1" name="enable" type="bool">
</argument>
<description>
+ Sets the interior value of this GI probe. A GI probe set to interior does not include the sky when calculating lighting. Equivalent to [member GIProbe.interior].
</description>
</method>
<method name="gi_probe_set_normal_bias">
@@ -1577,6 +1632,7 @@
<argument index="1" name="bias" type="float">
</argument>
<description>
+ Sets the normal bias for this GI probe. Normal bias behaves similar to the other form of bias and may help reduce self-occlusion. Equivalent to [member GIProbe.normal_bias].
</description>
</method>
<method name="gi_probe_set_propagation">
@@ -1587,6 +1643,7 @@
<argument index="1" name="propagation" type="float">
</argument>
<description>
+ Sets the propagation of light within this GI probe. Equivalent to [member GIProbe.propagation].
</description>
</method>
<method name="gi_probe_set_to_cell_xform">
@@ -1597,6 +1654,7 @@
<argument index="1" name="xform" type="Transform">
</argument>
<description>
+ Sets the to cell [Transform] for this GI probe.
</description>
</method>
<method name="has_changed" qualifiers="const">
@@ -1612,6 +1670,7 @@
<argument index="0" name="feature" type="int" enum="VisualServer.Features">
</argument>
<description>
+ Not yet implemented. Always returns [code]false[/code].
</description>
</method>
<method name="has_os_feature" qualifiers="const">
@@ -1660,7 +1719,9 @@
<return type="RID">
</return>
<description>
- Creates an [ImmediateGeometry] and adds it to the VisualServer. It can be accessed with the RID that is returned. This RID will be used in all [code]immediate_*[/code] VisualServer functions.
+ Creates an immediate geometry and adds it to the VisualServer. It can be accessed with the RID that is returned. This RID will be used in all [code]immediate_*[/code] VisualServer functions.
+ Once finished with your RID, you will want to free the RID using the VisualServer's [method free_rid] static method.
+ To place in a scene, attach this immediate geometry to an instance using [method instance_set_base] using the returned RID.
</description>
</method>
<method name="immediate_end">
@@ -1755,13 +1816,14 @@
<argument index="1" name="vertex" type="Vector2">
</argument>
<description>
+ Adds the next vertex using the information provided in advance. This is a helper class that calls [method immediate_vertex] under the hood. Equivalent to [method ImmediateGeometry.add_vertex].
</description>
</method>
<method name="init">
<return type="void">
</return>
<description>
- Initializes the visual server.
+ Initializes the visual server. This function is called internally by platform-dependent code during engine initialization. If called from a running game, it will not do anything.
</description>
</method>
<method name="instance_attach_object_instance_id">
@@ -1772,6 +1834,7 @@
<argument index="1" name="id" type="int">
</argument>
<description>
+ Attaches a unique Object ID to instance. Object ID must be attached to instance for proper culling with [method instances_cull_aabb], [method instances_cull_convex], and [method instances_cull_ray].
</description>
</method>
<method name="instance_attach_skeleton">
@@ -1782,12 +1845,16 @@
<argument index="1" name="skeleton" type="RID">
</argument>
<description>
+ Attaches a skeleton to an instance. Removes the previous skeleton from the instance.
</description>
</method>
<method name="instance_create">
<return type="RID">
</return>
<description>
+ Creates a visual instance and adds it to the VisualServer. It can be accessed with the RID that is returned. This RID will be used in all [code]instance_*[/code] VisualServer functions.
+ Once finished with your RID, you will want to free the RID using the VisualServer's [method free_rid] static method.
+ An instance is a way of placing a 3D object in the scenario. Objects like particles, meshes, and reflection probes need to be associated with an instance to be visible in the scenario using [method instance_set_base].
</description>
</method>
<method name="instance_create2">
@@ -1798,6 +1865,8 @@
<argument index="1" name="scenario" type="RID">
</argument>
<description>
+ Creates a visual instance, adds it to the VisualServer, and sets both base and scenario. It can be accessed with the RID that is returned. This RID will be used in all [code]instance_*[/code] VisualServer functions.
+ Once finished with your RID, you will want to free the RID using the VisualServer's [method free_rid] static method.
</description>
</method>
<method name="instance_geometry_set_as_instance_lod">
@@ -1808,6 +1877,7 @@
<argument index="1" name="as_lod_of_instance" type="RID">
</argument>
<description>
+ Not implemented in Godot 3.x.
</description>
</method>
<method name="instance_geometry_set_cast_shadows_setting">
@@ -1818,6 +1888,7 @@
<argument index="1" name="shadow_casting_setting" type="int" enum="VisualServer.ShadowCastingSetting">
</argument>
<description>
+ Sets the shadow casting setting to one of [enum ShadowCastingSetting]. Equivalent to [member GeometryInstance.cast_shadow].
</description>
</method>
<method name="instance_geometry_set_draw_range">
@@ -1834,6 +1905,7 @@
<argument index="4" name="max_margin" type="float">
</argument>
<description>
+ Not implemented in Godot 3.x.
</description>
</method>
<method name="instance_geometry_set_flag">
@@ -1846,6 +1918,7 @@
<argument index="2" name="enabled" type="bool">
</argument>
<description>
+ Sets the flag for a given [enum InstanceFlags]. See [enum InstanceFlags] for more details.
</description>
</method>
<method name="instance_geometry_set_material_override">
@@ -1856,6 +1929,7 @@
<argument index="1" name="material" type="RID">
</argument>
<description>
+ Sets a material that will override the material for all surfaces on the mesh associated with this instance. Equivalent to [member GeometryInstance.material_override].
</description>
</method>
<method name="instance_set_base">
@@ -1866,6 +1940,7 @@
<argument index="1" name="base" type="RID">
</argument>
<description>
+ Sets the base of the instance. A base can be any of the 3D objects that are created in the VisualServer that can be displayed. For example, any of the light types, mesh, multimesh, immediate geometry, particle system, reflection probe, lightmap capture, and the GI probe are all types that can be set as the base of an instance in order to be displayed in the scenario.
</description>
</method>
<method name="instance_set_blend_shape_weight">
@@ -1878,6 +1953,7 @@
<argument index="2" name="weight" type="float">
</argument>
<description>
+ Sets the weight for a given blend shape associated with this instance.
</description>
</method>
<method name="instance_set_custom_aabb">
@@ -1888,6 +1964,7 @@
<argument index="1" name="aabb" type="AABB">
</argument>
<description>
+ Sets a custom AABB to use when culling objects from the view frustum. Equivalent to [method GeometryInstance.set_custom_aabb].
</description>
</method>
<method name="instance_set_exterior">
@@ -1898,6 +1975,7 @@
<argument index="1" name="enabled" type="bool">
</argument>
<description>
+ Function not implemented in Godot 3.x.
</description>
</method>
<method name="instance_set_extra_visibility_margin">
@@ -1908,6 +1986,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 GeometryInstance.extra_cull_margin].
</description>
</method>
<method name="instance_set_layer_mask">
@@ -1918,6 +1997,7 @@
<argument index="1" name="mask" type="int">
</argument>
<description>
+ Sets the render layers that this instance will be drawn to. Equivalent to [member VisualInstance.layers].
</description>
</method>
<method name="instance_set_scenario">
@@ -1928,6 +2008,7 @@
<argument index="1" name="scenario" type="RID">
</argument>
<description>
+ Sets the scenario that the instance is in. The scenario is the 3D world that the objects will be displayed in.
</description>
</method>
<method name="instance_set_surface_material">
@@ -1940,6 +2021,7 @@
<argument index="2" name="material" type="RID">
</argument>
<description>
+ Sets the material of a specific surface. Equivalent to [method MeshInstance.set_surface_material].
</description>
</method>
<method name="instance_set_transform">
@@ -1950,6 +2032,7 @@
<argument index="1" name="transform" type="Transform">
</argument>
<description>
+ Sets the world space transform of the instance. Equivalent to [member Spatial.transform].
</description>
</method>
<method name="instance_set_use_lightmap">
@@ -1962,6 +2045,7 @@
<argument index="2" name="lightmap" type="RID">
</argument>
<description>
+ Sets the lightmap to use with this instance.
</description>
</method>
<method name="instance_set_visible">
@@ -1972,6 +2056,7 @@
<argument index="1" name="visible" type="bool">
</argument>
<description>
+ Sets whether an instance is drawn or not. Equivalent to [member Spatial.visible].
</description>
</method>
<method name="instances_cull_aabb" qualifiers="const">
@@ -1982,6 +2067,8 @@
<argument index="1" name="scenario" type="RID">
</argument>
<description>
+ Returns an array of object IDs intersecting with the provided AABB. Only visual 3D nodes are considered, such as [MeshInstance] or [DirectionalLight]. Use [method @GDScript.instance_from_id] to obtain the actual nodes. A scenario RID must be provided, which is available in the [World] you want to query. This forces an update for all resources queued to update.
+ [b]Warning:[/b] This function is primarily intended for editor usage. For in-game use cases, prefer physics collision.
</description>
</method>
<method name="instances_cull_convex" qualifiers="const">
@@ -1992,6 +2079,8 @@
<argument index="1" name="scenario" type="RID">
</argument>
<description>
+ Returns an array of object IDs intersecting with the provided convex shape. Only visual 3D nodes are considered, such as [MeshInstance] or [DirectionalLight]. Use [method @GDScript.instance_from_id] to obtain the actual nodes. A scenario RID must be provided, which is available in the [World] you want to query. This forces an update for all resources queued to update.
+ [b]Warning:[/b] This function is primarily intended for editor usage. For in-game use cases, prefer physics collision.
</description>
</method>
<method name="instances_cull_ray" qualifiers="const">
@@ -2004,7 +2093,7 @@
<argument index="2" name="scenario" type="RID">
</argument>
<description>
- Returns an array of object IDs intersecting with the provided 3D ray. Only visual 3D nodes are considered, such as [MeshInstance] or [DirectionalLight]. Use [method @GDScript.instance_from_id] to obtain the actual nodes. A scenario RID must be provided, which is available in the [World] you want to query.
+ Returns an array of object IDs intersecting with the provided 3D ray. Only visual 3D nodes are considered, such as [MeshInstance] or [DirectionalLight]. Use [method @GDScript.instance_from_id] to obtain the actual nodes. A scenario RID must be provided, which is available in the [World] you want to query. This forces an update for all resources queued to update.
[b]Warning:[/b] This function is primarily intended for editor usage. For in-game use cases, prefer physics collision.
</description>
</method>
@@ -2016,6 +2105,7 @@
<argument index="1" name="enable" type="bool">
</argument>
<description>
+ If [code]true[/code], this directional light will blend between shadow map splits resulting in a smoother transition between them. Equivalent to [member DirectionalLight.directional_shadow_blend_splits].
</description>
</method>
<method name="light_directional_set_shadow_depth_range_mode">
@@ -2026,6 +2116,7 @@
<argument index="1" name="range_mode" type="int" enum="VisualServer.LightDirectionalShadowDepthRangeMode">
</argument>
<description>
+ Sets the shadow depth range mode for this directional light. Equivalent to [member DirectionalLight.directional_shadow_depth_range]. See [enum LightDirectionalShadowDepthRangeMode] for options.
</description>
</method>
<method name="light_directional_set_shadow_mode">
@@ -2036,6 +2127,7 @@
<argument index="1" name="mode" type="int" enum="VisualServer.LightDirectionalShadowMode">
</argument>
<description>
+ Sets the shadow mode for this directional light. Equivalent to [member DirectionalLight.directional_shadow_mode]. See [enum LightDirectionalShadowMode] for options.
</description>
</method>
<method name="light_omni_set_shadow_detail">
@@ -2046,6 +2138,7 @@
<argument index="1" name="detail" type="int" enum="VisualServer.LightOmniShadowDetail">
</argument>
<description>
+ Sets whether to use vertical or horizontal detail for this omni light. This can be used to alleviate artifacts in the shadow map. Equivalent to [member OmniLight.omni_shadow_detail].
</description>
</method>
<method name="light_omni_set_shadow_mode">
@@ -2056,6 +2149,7 @@
<argument index="1" name="mode" type="int" enum="VisualServer.LightOmniShadowMode">
</argument>
<description>
+ Sets whether to use a dual paraboloid or a cubemap for the shadow map. Dual paraboloid is faster but may suffer from artifacts. Equivalent to [member OmniLight.omni_shadow_mode].
</description>
</method>
<method name="light_set_color">
@@ -2066,6 +2160,7 @@
<argument index="1" name="color" type="Color">
</argument>
<description>
+ Sets the color of the light. Equivalent to [member Light.light_color].
</description>
</method>
<method name="light_set_cull_mask">
@@ -2076,6 +2171,7 @@
<argument index="1" name="mask" type="int">
</argument>
<description>
+ Sets the cull mask for this Light. Lights only affect objects in the selected layers. Equivalent to [member Light.light_cull_mask].
</description>
</method>
<method name="light_set_negative">
@@ -2086,6 +2182,7 @@
<argument index="1" name="enable" type="bool">
</argument>
<description>
+ If [code]true[/code], light will subtract light instead of adding light. Equivalent to [member Light.light_negative].
</description>
</method>
<method name="light_set_param">
@@ -2098,6 +2195,7 @@
<argument index="2" name="value" type="float">
</argument>
<description>
+ Sets the specified light parameter. See [enum LightParam] for options. Equivalent to [method Light.set_param].
</description>
</method>
<method name="light_set_projector">
@@ -2108,6 +2206,7 @@
<argument index="1" name="texture" type="RID">
</argument>
<description>
+ Not implemented in Godot 3.x.
</description>
</method>
<method name="light_set_reverse_cull_face_mode">
@@ -2118,6 +2217,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 Light.shadow_reverse_cull_face].
</description>
</method>
<method name="light_set_shadow">
@@ -2128,6 +2228,7 @@
<argument index="1" name="enabled" type="bool">
</argument>
<description>
+ If [code]true[/code], light will cast shadows. Equivalent to [member Light.shadow_enabled].
</description>
</method>
<method name="light_set_shadow_color">
@@ -2138,6 +2239,7 @@
<argument index="1" name="color" type="Color">
</argument>
<description>
+ Sets the color of the shadow cast by the light. Equivalent to [member Light.shadow_color].
</description>
</method>
<method name="light_set_use_gi">
@@ -2155,6 +2257,9 @@
<return type="RID">
</return>
<description>
+ Creates a lightmap capture and adds it to the VisualServer. It can be accessed with the RID that is returned. This RID will be used in all [code]lightmap_capture_*[/code] VisualServer functions.
+ Once finished with your RID, you will want to free the RID using the VisualServer's [method free_rid] static method.
+ To place in a scene, attach this lightmap capture to an instance using [method instance_set_base] using the returned RID.
</description>
</method>
<method name="lightmap_capture_get_bounds" qualifiers="const">
@@ -2163,6 +2268,7 @@
<argument index="0" name="capture" type="RID">
</argument>
<description>
+ Returns the size of the lightmap capture area.
</description>
</method>
<method name="lightmap_capture_get_energy" qualifiers="const">
@@ -2171,6 +2277,7 @@
<argument index="0" name="capture" type="RID">
</argument>
<description>
+ Returns the energy multiplier used by the lightmap capture.
</description>
</method>
<method name="lightmap_capture_get_octree" qualifiers="const">
@@ -2179,6 +2286,7 @@
<argument index="0" name="capture" type="RID">
</argument>
<description>
+ Returns the octree used by the lightmap capture.
</description>
</method>
<method name="lightmap_capture_get_octree_cell_subdiv" qualifiers="const">
@@ -2187,6 +2295,7 @@
<argument index="0" name="capture" type="RID">
</argument>
<description>
+ Returns the cell subdivision amount used by this lightmap capture's octree.
</description>
</method>
<method name="lightmap_capture_get_octree_cell_transform" qualifiers="const">
@@ -2195,6 +2304,7 @@
<argument index="0" name="capture" type="RID">
</argument>
<description>
+ Returns the cell transform for this lightmap capture's octree.
</description>
</method>
<method name="lightmap_capture_set_bounds">
@@ -2205,6 +2315,7 @@
<argument index="1" name="bounds" type="AABB">
</argument>
<description>
+ Sets the size of the area covered by the lightmap capture. Equivalent to [member BakedLightmapData.bounds].
</description>
</method>
<method name="lightmap_capture_set_energy">
@@ -2215,6 +2326,7 @@
<argument index="1" name="energy" type="float">
</argument>
<description>
+ Sets the energy multiplier for this lightmap capture. Equivalent to [member BakedLightmapData.energy].
</description>
</method>
<method name="lightmap_capture_set_octree">
@@ -2225,6 +2337,7 @@
<argument index="1" name="octree" type="PoolByteArray">
</argument>
<description>
+ Sets the octree to be used by this lightmap capture. This function is normally used by the [BakedLightmap] node. Equivalent to [member BakedLightmapData.octree].
</description>
</method>
<method name="lightmap_capture_set_octree_cell_subdiv">
@@ -2235,6 +2348,7 @@
<argument index="1" name="subdiv" type="int">
</argument>
<description>
+ Sets the subdivision level of this lightmap capture's octree. Equivalent to [member BakedLightmapData.cell_subdiv].
</description>
</method>
<method name="lightmap_capture_set_octree_cell_transform">
@@ -2245,6 +2359,7 @@
<argument index="1" name="xform" type="Transform">
</argument>
<description>
+ Sets the octree cell transform for this lightmap capture's octree. Equivalent to [member BakedLightmapData.cell_space_transform].
</description>
</method>
<method name="make_sphere_mesh">
@@ -2264,7 +2379,8 @@
<return type="RID">
</return>
<description>
- Returns an empty material.
+ Creates an empty material and adds it to the VisualServer. It can be accessed with the RID that is returned. This RID will be used in all [code]material_*[/code] VisualServer functions.
+ Once finished with your RID, you will want to free the RID using the VisualServer's [method free_rid] static method.
</description>
</method>
<method name="material_get_param" qualifiers="const">
@@ -2286,6 +2402,7 @@
<argument index="1" name="parameter" type="String">
</argument>
<description>
+ Returns the default value for the param if available. Otherwise returns an empty [Variant].
</description>
</method>
<method name="material_get_shader" qualifiers="const">
@@ -2384,7 +2501,9 @@
<return type="RID">
</return>
<description>
- Creates a new mesh.
+ Creates a new mesh and adds it to the VisualServer. It can be accessed with the RID that is returned. This RID will be used in all [code]mesh_*[/code] VisualServer functions.
+ Once finished with your RID, you will want to free the RID using the VisualServer's [method free_rid] static method.
+ To place in a scene, attach this mesh to an instance using [method instance_set_base] using the returned RID.
</description>
</method>
<method name="mesh_get_blend_shape_count" qualifiers="const">
@@ -2556,6 +2675,7 @@
<argument index="3" name="array_index" type="int">
</argument>
<description>
+ Function is unused in Godot 3.x.
</description>
</method>
<method name="mesh_surface_get_format_stride" qualifiers="const">
@@ -2568,6 +2688,7 @@
<argument index="2" name="index_len" type="int">
</argument>
<description>
+ Function is unused in Godot 3.x.
</description>
</method>
<method name="mesh_surface_get_index_array" qualifiers="const">
@@ -2639,6 +2760,7 @@
<argument index="3" name="data" type="PoolByteArray">
</argument>
<description>
+ 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">
@@ -2655,14 +2777,16 @@
<argument index="4" name="custom_data_format" type="int" enum="VisualServer.MultimeshCustomDataFormat" default="0">
</argument>
<description>
+ Allocates space for the multimesh data. Format parameters determine how the data will be stored by OpenGL. See [enum MultimeshTransformFormat], [enum MultimeshColorFormat], and [enum MultimeshCustomDataFormat] for usage. Equivalent to [member MultiMesh.instance_count].
</description>
</method>
<method name="multimesh_create">
<return type="RID">
</return>
<description>
- Creates a new multimesh on the VisualServer and returns an [RID] handle.
+ Creates a new multimesh on the VisualServer and returns an [RID] handle. This RID will be used in all [code]multimesh_*[/code] VisualServer functions.
Once finished with your RID, you will want to free the RID using the VisualServer's [method free_rid] static method.
+ To place in a scene, attach this multimesh to an instance using [method instance_set_base] using the returned RID.
</description>
</method>
<method name="multimesh_get_aabb" qualifiers="const">
@@ -2671,6 +2795,7 @@
<argument index="0" name="multimesh" type="RID">
</argument>
<description>
+ Calculates and returns the axis-aligned bounding box that encloses all instances within the multimesh.
</description>
</method>
<method name="multimesh_get_instance_count" qualifiers="const">
@@ -2679,6 +2804,7 @@
<argument index="0" name="multimesh" type="RID">
</argument>
<description>
+ Returns the number of instances allocated for this multimesh.
</description>
</method>
<method name="multimesh_get_mesh" qualifiers="const">
@@ -2687,6 +2813,7 @@
<argument index="0" name="multimesh" type="RID">
</argument>
<description>
+ Returns the RID of the mesh that will be used in drawing this multimesh.
</description>
</method>
<method name="multimesh_get_visible_instances" qualifiers="const">
@@ -2695,6 +2822,7 @@
<argument index="0" name="multimesh" type="RID">
</argument>
<description>
+ Returns the number of visible instances for this multimesh.
</description>
</method>
<method name="multimesh_instance_get_color" qualifiers="const">
@@ -2705,6 +2833,7 @@
<argument index="1" name="index" type="int">
</argument>
<description>
+ Returns the color by which the specified instance will be modulated.
</description>
</method>
<method name="multimesh_instance_get_custom_data" qualifiers="const">
@@ -2715,6 +2844,7 @@
<argument index="1" name="index" type="int">
</argument>
<description>
+ Returns the custom data associated with the specified instance.
</description>
</method>
<method name="multimesh_instance_get_transform" qualifiers="const">
@@ -2725,6 +2855,7 @@
<argument index="1" name="index" type="int">
</argument>
<description>
+ Returns the [Transform] of the specified instance.
</description>
</method>
<method name="multimesh_instance_get_transform_2d" qualifiers="const">
@@ -2735,6 +2866,7 @@
<argument index="1" name="index" type="int">
</argument>
<description>
+ Returns the [Transform2D] of the specified instance. For use when the multimesh is set to use 2D transforms.
</description>
</method>
<method name="multimesh_instance_set_color">
@@ -2747,6 +2879,7 @@
<argument index="2" name="color" type="Color">
</argument>
<description>
+ Sets the color by which this instance will be modulated. Equivalent to [method MultiMesh.set_instance_color].
</description>
</method>
<method name="multimesh_instance_set_custom_data">
@@ -2759,6 +2892,7 @@
<argument index="2" name="custom_data" type="Color">
</argument>
<description>
+ Sets the custom data for this instance. Custom data is passed as a [Color], but is interpreted as a [code]vec4[/code] in the shader. Equivalent to [method MultiMesh.set_instance_custom_data].
</description>
</method>
<method name="multimesh_instance_set_transform">
@@ -2771,6 +2905,7 @@
<argument index="2" name="transform" type="Transform">
</argument>
<description>
+ Sets the [Transform] for this instance. Equivalent to [method MultiMesh.set_instance_transform].
</description>
</method>
<method name="multimesh_instance_set_transform_2d">
@@ -2783,6 +2918,7 @@
<argument index="2" name="transform" type="Transform2D">
</argument>
<description>
+ Sets the [Transform2D] for this instance. For use when multimesh is used in 2D. Equivalent to [method MultiMesh.set_instance_transform_2d].
</description>
</method>
<method name="multimesh_set_as_bulk_array">
@@ -2793,6 +2929,11 @@
<argument index="1" name="array" type="PoolRealArray">
</argument>
<description>
+ Sets all data related to the instances in one go. This is especially useful when loading the data from disk or preparing the data from GDNative.
+
+ All data is packed in one large float array. An array may look like this: Transform for instance 1, color data for instance 1, custom data for instance 1, transform for instance 2, color data for instance 2, etc.
+
+ [Transform] is stored as 12 floats, [Transform2D] is stored as 8 floats, [code]COLOR_8BIT[/code] / [code]CUSTOM_DATA_8BIT[/code] is stored as 1 float (4 bytes as is) and [code]COLOR_FLOAT[/code] / [code]CUSTOM_DATA_FLOAT[/code] is stored as 4 floats.
</description>
</method>
<method name="multimesh_set_mesh">
@@ -2803,6 +2944,7 @@
<argument index="1" name="mesh" type="RID">
</argument>
<description>
+ Sets the mesh to be drawn by the multimesh. Equivalent to [member MultiMesh.mesh].
</description>
</method>
<method name="multimesh_set_visible_instances">
@@ -2813,18 +2955,25 @@
<argument index="1" name="visible" type="int">
</argument>
<description>
+ Sets the number of instances visible at a given time. If -1, all instances that have been allocated are drawn. Equivalent to [member MultiMesh.visible_instance_count].
</description>
</method>
<method name="omni_light_create">
<return type="RID">
</return>
<description>
+ Creates a new omni light and adds it to the VisualServer. It can be accessed with the RID that is returned. This RID can be used in most [code]light_*[/code] VisualServer functions.
+ Once finished with your RID, you will want to free the RID using the VisualServer's [method free_rid] static method.
+ To place in a scene, attach this omni light to an instance using [method instance_set_base] using the returned RID.
</description>
</method>
<method name="particles_create">
<return type="RID">
</return>
<description>
+ Creates a particle system and adds it to the VisualServer. It can be accessed with the RID that is returned. This RID will be used in all [code]particles_*[/code] VisualServer functions.
+ Once finished with your RID, you will want to free the RID using the VisualServer's [method free_rid] static method.
+ To place in a scene, attach these particles to an instance using [method instance_set_base] using the returned RID.
</description>
</method>
<method name="particles_get_current_aabb">
@@ -2833,6 +2982,7 @@
<argument index="0" name="particles" type="RID">
</argument>
<description>
+ Calculates and returns the axis-aligned bounding box that contains all the particles. Equivalent to [method Particles.capture_aabb].
</description>
</method>
<method name="particles_get_emitting">
@@ -2841,6 +2991,7 @@
<argument index="0" name="particles" type="RID">
</argument>
<description>
+ Returns [code]true[/code] if particles are currently set to emitting.
</description>
</method>
<method name="particles_is_inactive">
@@ -2849,6 +3000,7 @@
<argument index="0" name="particles" type="RID">
</argument>
<description>
+ Returns [code]true[/code] if particles are not emitting and particles are set to inactive.
</description>
</method>
<method name="particles_request_process">
@@ -2857,6 +3009,7 @@
<argument index="0" name="particles" type="RID">
</argument>
<description>
+ Add particle system to list of particle systems that need to be updated. Update will take place on the next frame, or on the next call to [method instances_cull_aabb], [method instances_cull_convex], or [method instances_cull_ray].
</description>
</method>
<method name="particles_restart">
@@ -2865,6 +3018,7 @@
<argument index="0" name="particles" type="RID">
</argument>
<description>
+ Reset the particles on the next update. Equivalent to [method Particles.restart]
</description>
</method>
<method name="particles_set_amount">
@@ -2875,6 +3029,7 @@
<argument index="1" name="amount" type="int">
</argument>
<description>
+ Sets the number of particles to be drawn and allocates the memory for them. Equivalent to [member Particles.amount].
</description>
</method>
<method name="particles_set_custom_aabb">
@@ -2885,6 +3040,7 @@
<argument index="1" name="aabb" type="AABB">
</argument>
<description>
+ Sets a custom axis-aligned bounding box for the particle system. Equivalent to [member Particles.visibility_aabb].
</description>
</method>
<method name="particles_set_draw_order">
@@ -2895,6 +3051,7 @@
<argument index="1" name="order" type="int" enum="VisualServer.ParticlesDrawOrder">
</argument>
<description>
+ Sets the draw order of the particles to one of the named enums from [enum ParticlesDrawOrder]. See [enum ParticlesDrawOrder] for options. Equivalent to [member Particles.draw_order].
</description>
</method>
<method name="particles_set_draw_pass_mesh">
@@ -2907,6 +3064,7 @@
<argument index="2" name="mesh" type="RID">
</argument>
<description>
+ Sets the mesh to be used for the specified draw pass. Equivalent to [member Particles.draw_pass_1], [member Particles.draw_pass_2], [member Particles.draw_pass_3], and [member Particles.draw_pass_4].
</description>
</method>
<method name="particles_set_draw_passes">
@@ -2917,6 +3075,7 @@
<argument index="1" name="count" type="int">
</argument>
<description>
+ Sets the number of draw passes to use. Equivalent to [member Particles.draw_passes].
</description>
</method>
<method name="particles_set_emission_transform">
@@ -2927,6 +3086,7 @@
<argument index="1" name="transform" type="Transform">
</argument>
<description>
+ Sets the [Transform] that will be used by the particles when they first emit.
</description>
</method>
<method name="particles_set_emitting">
@@ -2937,6 +3097,7 @@
<argument index="1" name="emitting" type="bool">
</argument>
<description>
+ If [code]true[/code], particles will emit over time. Setting to false does not reset the particles, but only stops their emission. Equivalent to [member Particles.emitting].
</description>
</method>
<method name="particles_set_explosiveness_ratio">
@@ -2947,6 +3108,7 @@
<argument index="1" name="ratio" type="float">
</argument>
<description>
+ Sets the explosiveness ratio. Equivalent to [member Particles.explosiveness].
</description>
</method>
<method name="particles_set_fixed_fps">
@@ -2957,6 +3119,7 @@
<argument index="1" name="fps" type="int">
</argument>
<description>
+ Sets the frame rate that the particle system rendering will be fixed to. Equivalent to [member Particles.fixed_fps].
</description>
</method>
<method name="particles_set_fractional_delta">
@@ -2967,6 +3130,7 @@
<argument index="1" name="enable" type="bool">
</argument>
<description>
+ If [code]true[/code], uses fractional delta which smooths the movement of the particles. Equivalent to [member Particles.fract_delta].
</description>
</method>
<method name="particles_set_lifetime">
@@ -2977,6 +3141,7 @@
<argument index="1" name="lifetime" type="float">
</argument>
<description>
+ Sets the lifetime of each particle in the system. Equivalent to [member Particles.lifetime].
</description>
</method>
<method name="particles_set_one_shot">
@@ -2987,6 +3152,7 @@
<argument index="1" name="one_shot" type="bool">
</argument>
<description>
+ If [code]true[/code], particles will emit once and then stop. Equivalent to [member Particles.one_shot].
</description>
</method>
<method name="particles_set_pre_process_time">
@@ -2997,6 +3163,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 Particles.preprocess].
</description>
</method>
<method name="particles_set_process_material">
@@ -3007,6 +3174,7 @@
<argument index="1" name="material" type="RID">
</argument>
<description>
+ Sets the material for processing the particles. Note: this is not the material used to draw the materials. Equivalent to [member Particles.process_material].
</description>
</method>
<method name="particles_set_randomness_ratio">
@@ -3017,6 +3185,7 @@
<argument index="1" name="ratio" type="float">
</argument>
<description>
+ Sets the emission randomness ratio. This randomizes the emission of particles within their phase. Equivalent to [member Particles.randomness].
</description>
</method>
<method name="particles_set_speed_scale">
@@ -3027,6 +3196,7 @@
<argument index="1" name="scale" type="float">
</argument>
<description>
+ Sets the speed scale of the particle system. Equivalent to [member Particles.speed_scale].
</description>
</method>
<method name="particles_set_use_local_coordinates">
@@ -3037,12 +3207,16 @@
<argument index="1" name="enable" type="bool">
</argument>
<description>
+ If [code]true[/code], particles use local coordinates. If [code]false[/code] they use global coordinates. Equivalent to [member Particles.local_coords].
</description>
</method>
<method name="reflection_probe_create">
<return type="RID">
</return>
<description>
+ Creates a reflection probe and adds it to the VisualServer. It can be accessed with the RID that is returned. This RID will be used in all [code]reflection_probe_*[/code] VisualServer functions.
+ Once finished with your RID, you will want to free the RID using the VisualServer's [method free_rid] static method.
+ To place in a scene, attach this reflection probe to an instance using [method instance_set_base] using the returned RID.
</description>
</method>
<method name="reflection_probe_set_as_interior">
@@ -3053,6 +3227,7 @@
<argument index="1" name="enable" type="bool">
</argument>
<description>
+ If [code]true[/code], reflections will ignore sky contribution. Equivalent to [member ReflectionProbe.interior_enable].
</description>
</method>
<method name="reflection_probe_set_cull_mask">
@@ -3063,6 +3238,7 @@
<argument index="1" name="layers" type="int">
</argument>
<description>
+ Sets the render cull mask for this reflection probe. Only instances with a matching cull mask will be rendered by this probe. Equivalent to [member ReflectionProbe.cull_mask].
</description>
</method>
<method name="reflection_probe_set_enable_box_projection">
@@ -3073,6 +3249,7 @@
<argument index="1" name="enable" type="bool">
</argument>
<description>
+ If [code]true[/code], uses box projection. This can make reflections look more correct in certain situations. Equivalent to [member ReflectionProbe.box_projection].
</description>
</method>
<method name="reflection_probe_set_enable_shadows">
@@ -3083,6 +3260,7 @@
<argument index="1" name="enable" type="bool">
</argument>
<description>
+ If [code]true[/code], computes shadows in the reflection probe. This makes the reflection much slower to compute. Equivalent to [member ReflectionProbe.enable_shadows].
</description>
</method>
<method name="reflection_probe_set_extents">
@@ -3093,6 +3271,7 @@
<argument index="1" name="extents" type="Vector3">
</argument>
<description>
+ Sets the size of the area that the reflection probe will capture. Equivalent to [member ReflectionProbe.extents].
</description>
</method>
<method name="reflection_probe_set_intensity">
@@ -3103,6 +3282,7 @@
<argument index="1" name="intensity" type="float">
</argument>
<description>
+ Sets the intensity of the reflection probe. Intensity modulates the strength of the reflection. Equivalent to [member ReflectionProbe.intensity].
</description>
</method>
<method name="reflection_probe_set_interior_ambient">
@@ -3113,6 +3293,7 @@
<argument index="1" name="color" type="Color">
</argument>
<description>
+ Sets the ambient light color for this reflection probe when set to interior mode. Equivalent to [member ReflectionProbe.interior_ambient_color].
</description>
</method>
<method name="reflection_probe_set_interior_ambient_energy">
@@ -3123,6 +3304,7 @@
<argument index="1" name="energy" type="float">
</argument>
<description>
+ Sets the energy multiplier for this reflection probes ambient light contribution when set to interior mode. Equivalent to [member ReflectionProbe.interior_ambient_energy].
</description>
</method>
<method name="reflection_probe_set_interior_ambient_probe_contribution">
@@ -3133,6 +3315,7 @@
<argument index="1" name="contrib" type="float">
</argument>
<description>
+ Sets the contribution value for how much the reflection affects the ambient light for this reflection probe when set to interior mode. Useful so that ambient light matches the color of the room. Equivalent to [member ReflectionProbe.interior_ambient_contrib].
</description>
</method>
<method name="reflection_probe_set_max_distance">
@@ -3143,6 +3326,7 @@
<argument index="1" name="distance" type="float">
</argument>
<description>
+ Sets the max distance away from the probe an object can be before it is culled. Equivalent to [member ReflectionProbe.max_distance].
</description>
</method>
<method name="reflection_probe_set_origin_offset">
@@ -3153,6 +3337,7 @@
<argument index="1" name="offset" type="Vector3">
</argument>
<description>
+ Sets the origin offset to be used when this reflection probe is in box project mode. Equivalent to [member ReflectionProbe.origin_offset].
</description>
</method>
<method name="reflection_probe_set_update_mode">
@@ -3163,6 +3348,7 @@
<argument index="1" name="mode" type="int" enum="VisualServer.ReflectionProbeUpdateMode">
</argument>
<description>
+ Sets how often the reflection probe updates. Can either be once or every frame. See [enum ReflectionProbeUpdateMode] for options.
</description>
</method>
<method name="request_frame_drawn_callback">
@@ -3183,6 +3369,9 @@
<return type="RID">
</return>
<description>
+ Creates a scenario and adds it to the VisualServer. It can be accessed with the RID that is returned. This RID will be used in all [code]scenario_*[/code] VisualServer functions.
+ Once finished with your RID, you will want to free the RID using the VisualServer's [method free_rid] static method.
+ The scenario is the 3D world that all the visual instances exist in.
</description>
</method>
<method name="scenario_set_debug">
@@ -3193,6 +3382,7 @@
<argument index="1" name="debug_mode" type="int" enum="VisualServer.ScenarioDebugMode">
</argument>
<description>
+ Sets the [enum ScenarioDebugMode] for this scenario. See [enum ScenarioDebugMode] for options.
</description>
</method>
<method name="scenario_set_environment">
@@ -3203,6 +3393,7 @@
<argument index="1" name="environment" type="RID">
</argument>
<description>
+ Sets the environment that will be used with this scenario.
</description>
</method>
<method name="scenario_set_fallback_environment">
@@ -3213,6 +3404,7 @@
<argument index="1" name="environment" type="RID">
</argument>
<description>
+ Sets the fallback environment to be used by this scenario. The fallback environment is used if no environment is set. Internally, this is used by the editor to provide a default environment.
</description>
</method>
<method name="scenario_set_reflection_atlas_size">
@@ -3225,6 +3417,7 @@
<argument index="2" name="subdiv" type="int">
</argument>
<description>
+ Sets the size of the reflection atlas shared by all reflection probes in this scenario.
</description>
</method>
<method name="set_boot_image">
@@ -3248,6 +3441,7 @@
<argument index="0" name="generate" type="bool">
</argument>
<description>
+ If [code]true[/code], the engine will generate wireframes for use with the wireframe debug mode.
</description>
</method>
<method name="set_default_clear_color">
@@ -3256,13 +3450,15 @@
<argument index="0" name="color" type="Color">
</argument>
<description>
+ Sets the default clear color which is used when a specific clear color has not been selected.
</description>
</method>
<method name="shader_create">
<return type="RID">
</return>
<description>
- Creates an empty shader.
+ Creates an empty shader and adds it to the VisualServer. It can be accessed with the RID that is returned. This RID will be used in all [code]shader_*[/code] VisualServer functions.
+ Once finished with your RID, you will want to free the RID using the VisualServer's [method free_rid] static method.
</description>
</method>
<method name="shader_get_code" qualifiers="const">
@@ -3328,6 +3524,7 @@
<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">
@@ -3338,6 +3535,7 @@
<argument index="1" name="bone" type="int">
</argument>
<description>
+ Returns the [Transform] set for a specific bone of this skeleton.
</description>
</method>
<method name="skeleton_bone_get_transform_2d" qualifiers="const">
@@ -3348,6 +3546,7 @@
<argument index="1" name="bone" type="int">
</argument>
<description>
+ Returns the [Transform2D] set for a specific bone of this skeleton.
</description>
</method>
<method name="skeleton_bone_set_transform">
@@ -3360,6 +3559,7 @@
<argument index="2" name="transform" type="Transform">
</argument>
<description>
+ Sets the [Transform] for a specific bone of this skeleton.
</description>
</method>
<method name="skeleton_bone_set_transform_2d">
@@ -3372,12 +3572,15 @@
<argument index="2" name="transform" type="Transform2D">
</argument>
<description>
+ Sets the [Transform2D] for a specific bone of this skeleton.
</description>
</method>
<method name="skeleton_create">
<return type="RID">
</return>
<description>
+ Creates a skeleton and adds it to the VisualServer. It can be accessed with the RID that is returned. This RID will be used in all [code]skeleton_*[/code] VisualServer functions.
+ Once finished with your RID, you will want to free the RID using the VisualServer's [method free_rid] static method.
</description>
</method>
<method name="skeleton_get_bone_count" qualifiers="const">
@@ -3386,13 +3589,15 @@
<argument index="0" name="skeleton" type="RID">
</argument>
<description>
+ Returns the number of bones allocated for this skeleton.
</description>
</method>
<method name="sky_create">
<return type="RID">
</return>
<description>
- Creates an empty sky.
+ Creates an empty sky and adds it to the VisualServer. It can be accessed with the RID that is returned. This RID will be used in all [code]sky_*[/code] VisualServer functions.
+ Once finished with your RID, you will want to free the RID using the VisualServer's [method free_rid] static method.
</description>
</method>
<method name="sky_set_texture">
@@ -3412,12 +3617,16 @@
<return type="RID">
</return>
<description>
+ Creates a spot light and adds it to the VisualServer. It can be accessed with the RID that is returned. This RID can be used in most [code]light_*[/code] VisualServer functions.
+ Once finished with your RID, you will want to free the RID using the VisualServer's [method free_rid] static method.
+ To place in a scene, attach this spot light to an instance using [method instance_set_base] using the returned RID.
</description>
</method>
<method name="sync">
<return type="void">
</return>
<description>
+ Not implemented in Godot 3.x.
</description>
</method>
<method name="texture_allocate">
@@ -3438,6 +3647,7 @@
<argument index="6" name="flags" type="int" default="7">
</argument>
<description>
+ Allocates the GPU memory for the texture.
</description>
</method>
<method name="texture_bind">
@@ -3455,7 +3665,8 @@
<return type="RID">
</return>
<description>
- Creates an empty texture.
+ Creates an empty texture and adds it to the VisualServer. It can be accessed with the RID that is returned. This RID will be used in all [code]texture_*[/code] VisualServer functions.
+ Once finished with your RID, you will want to free the RID using the VisualServer's [method free_rid] static method.
</description>
</method>
<method name="texture_create_from_image">
@@ -3493,6 +3704,7 @@
<argument index="0" name="texture" type="RID">
</argument>
<description>
+ Returns the depth of the texture.
</description>
</method>
<method name="texture_get_flags" qualifiers="const">
@@ -3546,6 +3758,7 @@
<argument index="0" name="texture" type="RID">
</argument>
<description>
+ Returns the type of the texture, can be any of the [enum TextureType].
</description>
</method>
<method name="texture_get_width" qualifiers="const">
@@ -3594,6 +3807,7 @@
<argument index="9" name="layer" type="int" default="0">
</argument>
<description>
+ Sets a part of the data for a texture. Warning: this function calls the underlying graphics API directly and may corrupt your texture if used improperly.
</description>
</method>
<method name="texture_set_flags">
@@ -3639,6 +3853,7 @@
<argument index="3" name="depth" type="int">
</argument>
<description>
+ Resizes the texture to the specified dimensions.
</description>
</method>
<method name="textures_keep_original">
@@ -3696,7 +3911,8 @@
<return type="RID">
</return>
<description>
- Creates an empty viewport.
+ Creates an empty viewport and adds it to the VisualServer. It can be accessed with the RID that is returned. This RID will be used in all [code]viewport_*[/code] VisualServer functions.
+ Once finished with your RID, you will want to free the RID using the VisualServer's [method free_rid] static method.
</description>
</method>
<method name="viewport_detach">
@@ -3864,6 +4080,7 @@
<argument index="1" name="hidden" type="bool">
</argument>
<description>
+ Currently unimplemented in Godot 3.x.
</description>
</method>
<method name="viewport_set_msaa">
@@ -4021,6 +4238,7 @@
Marks an error that shows that the index array is empty.
</constant>
<constant name="ARRAY_WEIGHTS_SIZE" value="4">
+ Number of weights/bones per vertex.
</constant>
<constant name="CANVAS_ITEM_Z_MIN" value="-4096">
The minimum Z-layer for canvas items.
@@ -4029,8 +4247,10 @@
The maximum Z-layer for canvas items.
</constant>
<constant name="MAX_GLOW_LEVELS" value="7">
+ Max number of glow levels that can be used with glow post-process effect.
</constant>
<constant name="MAX_CURSORS" value="8">
+ Unused enum in Godot 3.x.
</constant>
<constant name="MATERIAL_RENDER_PRIORITY_MIN" value="-128">
The minimum renderpriority of all materials.
@@ -4057,12 +4277,16 @@
Marks the back side of a cubemap.
</constant>
<constant name="TEXTURE_TYPE_2D" value="0" enum="TextureType">
+ Normal texture with 2 dimensions, width and height.
</constant>
<constant name="TEXTURE_TYPE_CUBEMAP" value="1" enum="TextureType">
+ Texture made up of six faces, can be looked up with a [code]vec3[/code] in shader.
</constant>
<constant name="TEXTURE_TYPE_2D_ARRAY" value="2" enum="TextureType">
+ An array of 2-dimensional textures.
</constant>
<constant name="TEXTURE_TYPE_3D" value="3" enum="TextureType">
+ A 3-dimensional texture with width, height, and depth.
</constant>
<constant name="TEXTURE_FLAG_MIPMAPS" value="1" enum="TextureFlags">
Generates mipmaps, which are smaller versions of the same texture to use when zoomed out, keeping the aspect ratio.
@@ -4177,11 +4401,13 @@
Flag used to mark a compressed (half float) UV coordinates array for the second UV coordinates.
</constant>
<constant name="ARRAY_COMPRESS_BONES" value="32768" enum="ArrayFormat">
+ Flag used to mark a compressed bone array.
</constant>
<constant name="ARRAY_COMPRESS_WEIGHTS" value="65536" enum="ArrayFormat">
Flag used to mark a compressed (half float) weight array.
</constant>
<constant name="ARRAY_COMPRESS_INDEX" value="131072" enum="ArrayFormat">
+ Flag used to mark a compressed index array.
</constant>
<constant name="ARRAY_FLAG_USE_2D_VERTICES" value="262144" enum="ArrayFormat">
Flag used to mark that the array contains 2D vertices.
@@ -4217,8 +4443,10 @@
Represents the size of the [enum PrimitiveType] enum.
</constant>
<constant name="BLEND_SHAPE_MODE_NORMALIZED" value="0" enum="BlendShapeMode">
+ Blend shapes are normalized.
</constant>
<constant name="BLEND_SHAPE_MODE_RELATIVE" value="1" enum="BlendShapeMode">
+ Blend shapes are relative to base weight.
</constant>
<constant name="LIGHT_DIRECTIONAL" value="0" enum="LightType">
Is a directional (sun) light.
@@ -4251,47 +4479,67 @@
Scales the shadow color.
</constant>
<constant name="LIGHT_PARAM_SHADOW_MAX_DISTANCE" value="8" enum="LightParam">
+ Max distance that shadows will be rendered.
</constant>
<constant name="LIGHT_PARAM_SHADOW_SPLIT_1_OFFSET" value="9" enum="LightParam">
+ Proportion of shadow atlas occupied by the first split.
</constant>
<constant name="LIGHT_PARAM_SHADOW_SPLIT_2_OFFSET" value="10" enum="LightParam">
+ Proportion of shadow atlas occupied by the second split.
</constant>
<constant name="LIGHT_PARAM_SHADOW_SPLIT_3_OFFSET" value="11" enum="LightParam">
+ Proportion of shadow atlas occupied by the third split. The fourth split occupies the rest.
</constant>
<constant name="LIGHT_PARAM_SHADOW_NORMAL_BIAS" value="12" enum="LightParam">
+ Normal bias used to offset shadow lookup by object normal. Can be used to fix self-shadowing artifacts.
</constant>
<constant name="LIGHT_PARAM_SHADOW_BIAS" value="13" enum="LightParam">
+ Bias the shadow lookup to fix self-shadowing artifacts.
</constant>
<constant name="LIGHT_PARAM_SHADOW_BIAS_SPLIT_SCALE" value="14" enum="LightParam">
+ Increases bias on further splits to fix self-shadowing that only occurs far away from the camera.
</constant>
<constant name="LIGHT_PARAM_MAX" value="15" enum="LightParam">
Represents the size of the [enum LightParam] enum.
</constant>
<constant name="LIGHT_OMNI_SHADOW_DUAL_PARABOLOID" value="0" enum="LightOmniShadowMode">
+ Use a dual paraboloid shadow map for omni lights.
</constant>
<constant name="LIGHT_OMNI_SHADOW_CUBE" value="1" enum="LightOmniShadowMode">
+ Use a cubemap shadow map for omni lights. Slower but better quality than dual paraboloid.
</constant>
<constant name="LIGHT_OMNI_SHADOW_DETAIL_VERTICAL" value="0" enum="LightOmniShadowDetail">
+ Use more detail vertically when computing shadow map.
</constant>
<constant name="LIGHT_OMNI_SHADOW_DETAIL_HORIZONTAL" value="1" enum="LightOmniShadowDetail">
+ Use more detail horizontally when computing shadow map.
</constant>
<constant name="LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL" value="0" enum="LightDirectionalShadowMode">
+ Use orthogonal shadow projection for directional light.
</constant>
<constant name="LIGHT_DIRECTIONAL_SHADOW_PARALLEL_2_SPLITS" value="1" enum="LightDirectionalShadowMode">
+ Use 2 splits for shadow projection when using directional light.
</constant>
<constant name="LIGHT_DIRECTIONAL_SHADOW_PARALLEL_4_SPLITS" value="2" enum="LightDirectionalShadowMode">
+ Use 4 splits for shadow projection when using directional light.
</constant>
<constant name="LIGHT_DIRECTIONAL_SHADOW_DEPTH_RANGE_STABLE" value="0" enum="LightDirectionalShadowDepthRangeMode">
+ Keeps shadows stable as camera moves but has lower effective resolution.
</constant>
<constant name="LIGHT_DIRECTIONAL_SHADOW_DEPTH_RANGE_OPTIMIZED" value="1" enum="LightDirectionalShadowDepthRangeMode">
+ Optimize use of shadow maps, increasing the effective resolution. But may result in shadows moving or flickering slightly.
</constant>
<constant name="VIEWPORT_UPDATE_DISABLED" value="0" enum="ViewportUpdateMode">
+ Do not update the viewport.
</constant>
<constant name="VIEWPORT_UPDATE_ONCE" value="1" enum="ViewportUpdateMode">
+ Update the viewport once then set to disabled.
</constant>
<constant name="VIEWPORT_UPDATE_WHEN_VISIBLE" value="2" enum="ViewportUpdateMode">
+ Update the viewport whenever it is visible.
</constant>
<constant name="VIEWPORT_UPDATE_ALWAYS" value="3" enum="ViewportUpdateMode">
+ Always update the viewport.
</constant>
<constant name="VIEWPORT_CLEAR_ALWAYS" value="0" enum="ViewportClearMode">
The viewport is always cleared before drawing.
@@ -4336,16 +4584,22 @@
The Viewport renders 3D but without effects.
</constant>
<constant name="VIEWPORT_RENDER_INFO_OBJECTS_IN_FRAME" value="0" enum="ViewportRenderInfo">
+ Number of objects drawn in a single frame.
</constant>
<constant name="VIEWPORT_RENDER_INFO_VERTICES_IN_FRAME" value="1" enum="ViewportRenderInfo">
+ Number of vertices drawn in a single frame.
</constant>
<constant name="VIEWPORT_RENDER_INFO_MATERIAL_CHANGES_IN_FRAME" value="2" enum="ViewportRenderInfo">
+ Number of material changes during this frame.
</constant>
<constant name="VIEWPORT_RENDER_INFO_SHADER_CHANGES_IN_FRAME" value="3" enum="ViewportRenderInfo">
+ Number of shader changes during this frame.
</constant>
<constant name="VIEWPORT_RENDER_INFO_SURFACE_CHANGES_IN_FRAME" value="4" enum="ViewportRenderInfo">
+ Number of surface changes during this frame.
</constant>
<constant name="VIEWPORT_RENDER_INFO_DRAW_CALLS_IN_FRAME" value="5" enum="ViewportRenderInfo">
+ Number of draw calls during this frame.
</constant>
<constant name="VIEWPORT_RENDER_INFO_MAX" value="6" enum="ViewportRenderInfo">
Represents the size of the [enum ViewportRenderInfo] enum.
@@ -4363,12 +4617,16 @@
Debug draw draws objects in wireframe.
</constant>
<constant name="SCENARIO_DEBUG_DISABLED" value="0" enum="ScenarioDebugMode">
+ Do not use a debug mode.
</constant>
<constant name="SCENARIO_DEBUG_WIREFRAME" value="1" enum="ScenarioDebugMode">
+ Draw all objects as wireframe models.
</constant>
<constant name="SCENARIO_DEBUG_OVERDRAW" value="2" enum="ScenarioDebugMode">
+ Draw all objects in a way that displays how much overdraw is occurring. Overdraw occurs when a section of pixels is drawn and shaded and then another object covers it up. To optimize a scene, you should reduce overdraw.
</constant>
<constant name="SCENARIO_DEBUG_SHADELESS" value="3" enum="ScenarioDebugMode">
+ Draw all objects without shading. Equivalent to setting all objects shaders to [code]unshaded[/code].
</constant>
<constant name="INSTANCE_NONE" value="0" enum="InstanceType">
The instance does not have a type.
@@ -4389,10 +4647,13 @@
The instance is a light.
</constant>
<constant name="INSTANCE_REFLECTION_PROBE" value="6" enum="InstanceType">
+ The instance is a reflection probe.
</constant>
<constant name="INSTANCE_GI_PROBE" value="7" enum="InstanceType">
+ The instance is a GI probe.
</constant>
<constant name="INSTANCE_LIGHTMAP_CAPTURE" value="8" enum="InstanceType">
+ The instance is a lightmap capture.
</constant>
<constant name="INSTANCE_MAX" value="9" enum="InstanceType">
Represents the size of the [enum InstanceType] enum.
@@ -4401,19 +4662,25 @@
A combination of the flags of geometry instances (mesh, multimesh, immediate and particles).
</constant>
<constant name="INSTANCE_FLAG_USE_BAKED_LIGHT" value="0" enum="InstanceFlags">
+ Allows the instance to be used in baked lighting.
</constant>
<constant name="INSTANCE_FLAG_DRAW_NEXT_FRAME_IF_VISIBLE" value="1" enum="InstanceFlags">
+ When set, manually requests to draw geometry on next frame.
</constant>
<constant name="INSTANCE_FLAG_MAX" value="2" enum="InstanceFlags">
Represents the size of the [enum InstanceFlags] enum.
</constant>
<constant name="SHADOW_CASTING_SETTING_OFF" value="0" enum="ShadowCastingSetting">
+ Disable shadows from this instance.
</constant>
<constant name="SHADOW_CASTING_SETTING_ON" value="1" enum="ShadowCastingSetting">
+ Cast shadows from this instance.
</constant>
<constant name="SHADOW_CASTING_SETTING_DOUBLE_SIDED" value="2" enum="ShadowCastingSetting">
+ Disable backface culling when rendering the shadow of the object. This is slightly slower but may result in more correct shadows.
</constant>
<constant name="SHADOW_CASTING_SETTING_SHADOWS_ONLY" value="3" enum="ShadowCastingSetting">
+ Only render the shadows from the object. The object itself will not be drawn.
</constant>
<constant name="NINE_PATCH_STRETCH" value="0" enum="NinePatchAxisMode">
The nine patch gets stretched where needed.
@@ -4437,16 +4704,22 @@
The light adds color depending on mask.
</constant>
<constant name="CANVAS_LIGHT_FILTER_NONE" value="0" enum="CanvasLightShadowFilter">
+ Do not apply a filter to canvas light shadows.
</constant>
<constant name="CANVAS_LIGHT_FILTER_PCF3" value="1" enum="CanvasLightShadowFilter">
+ Use PCF3 filtering to filter canvas light shadows.
</constant>
<constant name="CANVAS_LIGHT_FILTER_PCF5" value="2" enum="CanvasLightShadowFilter">
+ Use PCF5 filtering to filter canvas light shadows.
</constant>
<constant name="CANVAS_LIGHT_FILTER_PCF7" value="3" enum="CanvasLightShadowFilter">
+ Use PCF7 filtering to filter canvas light shadows.
</constant>
<constant name="CANVAS_LIGHT_FILTER_PCF9" value="4" enum="CanvasLightShadowFilter">
+ Use PCF9 filtering to filter canvas light shadows.
</constant>
<constant name="CANVAS_LIGHT_FILTER_PCF13" value="5" enum="CanvasLightShadowFilter">
+ Use PCF13 filtering to filter canvas light shadows.
</constant>
<constant name="CANVAS_OCCLUDER_POLYGON_CULL_DISABLED" value="0" enum="CanvasOccluderPolygonCullMode">
Culling of the canvas occluder is disabled.
@@ -4488,85 +4761,124 @@
The amount of vertex memory used.
</constant>
<constant name="FEATURE_SHADERS" value="0" enum="Features">
+ Hardware supports shaders. This enum is currently unused in Godot 3.x.
</constant>
<constant name="FEATURE_MULTITHREADED" value="1" enum="Features">
+ Hardware supports multithreading. This enum is currently unused in Godot 3.x.
</constant>
<constant name="MULTIMESH_TRANSFORM_2D" value="0" enum="MultimeshTransformFormat">
+ Use [Transform2D] to store MultiMesh transform.
</constant>
<constant name="MULTIMESH_TRANSFORM_3D" value="1" enum="MultimeshTransformFormat">
+ Use [Transform] to store MultiMesh transform.
</constant>
<constant name="MULTIMESH_COLOR_NONE" value="0" enum="MultimeshColorFormat">
+ MultiMesh does not use per-instance color.
</constant>
<constant name="MULTIMESH_COLOR_8BIT" value="1" enum="MultimeshColorFormat">
+ MultiMesh color uses 8 bits per component. This packs the color into a single float.
</constant>
<constant name="MULTIMESH_COLOR_FLOAT" value="2" enum="MultimeshColorFormat">
+ MultiMesh color uses a float per channel.
</constant>
<constant name="MULTIMESH_CUSTOM_DATA_NONE" value="0" enum="MultimeshCustomDataFormat">
+ MultiMesh does not use custom data.
</constant>
<constant name="MULTIMESH_CUSTOM_DATA_8BIT" value="1" enum="MultimeshCustomDataFormat">
+ MultiMesh custom data uses 8 bits per component. This packs the 4-component custom data into a single float.
</constant>
<constant name="MULTIMESH_CUSTOM_DATA_FLOAT" value="2" enum="MultimeshCustomDataFormat">
+ MultiMesh custom data uses a float per component.
</constant>
<constant name="REFLECTION_PROBE_UPDATE_ONCE" value="0" enum="ReflectionProbeUpdateMode">
+ Reflection probe will update reflections once and then stop.
</constant>
<constant name="REFLECTION_PROBE_UPDATE_ALWAYS" value="1" enum="ReflectionProbeUpdateMode">
+ Reflection probe will update each frame. This mode is necessary to capture moving objects.
</constant>
<constant name="PARTICLES_DRAW_ORDER_INDEX" value="0" enum="ParticlesDrawOrder">
+ Draw particles in the order that they appear in the particles array.
</constant>
<constant name="PARTICLES_DRAW_ORDER_LIFETIME" value="1" enum="ParticlesDrawOrder">
+ Sort particles based on their lifetime.
</constant>
<constant name="PARTICLES_DRAW_ORDER_VIEW_DEPTH" value="2" enum="ParticlesDrawOrder">
+ Sort particles based on their distance to the camera.
</constant>
<constant name="ENV_BG_CLEAR_COLOR" value="0" enum="EnvironmentBG">
+ Use the clear color as background.
</constant>
<constant name="ENV_BG_COLOR" value="1" enum="EnvironmentBG">
+ Use a specified color as the background.
</constant>
<constant name="ENV_BG_SKY" value="2" enum="EnvironmentBG">
+ Use a sky resource for the background.
</constant>
<constant name="ENV_BG_COLOR_SKY" value="3" enum="EnvironmentBG">
+ Use a custom color for background, but use a sky for shading and reflections.
</constant>
<constant name="ENV_BG_CANVAS" value="4" enum="EnvironmentBG">
+ Use a specified canvas layer as the background. This can be useful for instantiating a 2D scene in a 3D world.
</constant>
<constant name="ENV_BG_KEEP" value="5" enum="EnvironmentBG">
+ Do not clear the background, use whatever was rendered last frame as the background.
</constant>
<constant name="ENV_BG_MAX" value="7" enum="EnvironmentBG">
Represents the size of the [enum EnvironmentBG] enum.
</constant>
<constant name="ENV_DOF_BLUR_QUALITY_LOW" value="0" enum="EnvironmentDOFBlurQuality">
+ Use lowest blur quality. Fastest, but may look bad.
</constant>
<constant name="ENV_DOF_BLUR_QUALITY_MEDIUM" value="1" enum="EnvironmentDOFBlurQuality">
+ Use medium blur quality.
</constant>
<constant name="ENV_DOF_BLUR_QUALITY_HIGH" value="2" enum="EnvironmentDOFBlurQuality">
+ Used highest blur quality. Looks the best, but is the slowest.
</constant>
<constant name="GLOW_BLEND_MODE_ADDITIVE" value="0" enum="EnvironmentGlowBlendMode">
+ Add the effect of the glow on top of the scene.
</constant>
<constant name="GLOW_BLEND_MODE_SCREEN" value="1" enum="EnvironmentGlowBlendMode">
+ Blends the glow effect with the screen. Does not get as bright as additive.
</constant>
<constant name="GLOW_BLEND_MODE_SOFTLIGHT" value="2" enum="EnvironmentGlowBlendMode">
+ Produces a subtle color disturbance around objects.
</constant>
<constant name="GLOW_BLEND_MODE_REPLACE" value="3" enum="EnvironmentGlowBlendMode">
+ Shows the glow effect by itself without the underlying scene.
</constant>
<constant name="ENV_TONE_MAPPER_LINEAR" value="0" enum="EnvironmentToneMapper">
+ Output color as they came in.
</constant>
<constant name="ENV_TONE_MAPPER_REINHARD" value="1" enum="EnvironmentToneMapper">
+ Use the Reinhard tonemapper.
</constant>
<constant name="ENV_TONE_MAPPER_FILMIC" value="2" enum="EnvironmentToneMapper">
+ Use the filmic tonemapper.
</constant>
<constant name="ENV_TONE_MAPPER_ACES" value="3" enum="EnvironmentToneMapper">
+ Use the ACES tonemapper.
</constant>
<constant name="ENV_SSAO_QUALITY_LOW" value="0" enum="EnvironmentSSAOQuality">
+ Lowest quality of screen space ambient occlusion.
</constant>
<constant name="ENV_SSAO_QUALITY_MEDIUM" value="1" enum="EnvironmentSSAOQuality">
+ Medium quality screen space ambient occlusion.
</constant>
<constant name="ENV_SSAO_QUALITY_HIGH" value="2" enum="EnvironmentSSAOQuality">
+ Highest quality screen space ambient occlusion.
</constant>
<constant name="ENV_SSAO_BLUR_DISABLED" value="0" enum="EnvironmentSSAOBlur">
+ Disables the blur set for SSAO. Will make SSAO look noisier.
</constant>
<constant name="ENV_SSAO_BLUR_1x1" value="1" enum="EnvironmentSSAOBlur">
+ Perform a 1x1 blur on the SSAO output.
</constant>
<constant name="ENV_SSAO_BLUR_2x2" value="2" enum="EnvironmentSSAOBlur">
+ Performs a 2x2 blur on the SSAO output.
</constant>
<constant name="ENV_SSAO_BLUR_3x3" value="3" enum="EnvironmentSSAOBlur">
+ Performs a 3x3 blur on the SSAO output. Use this for smoothest SSAO.
</constant>
</constants>
</class>
diff --git a/doc/classes/VisualShaderNodeFresnel.xml b/doc/classes/VisualShaderNodeFresnel.xml
index f79ae04abf..b71f5c6f37 100644
--- a/doc/classes/VisualShaderNodeFresnel.xml
+++ b/doc/classes/VisualShaderNodeFresnel.xml
@@ -9,7 +9,7 @@
<methods>
</methods>
<members>
- <member name="default_input_values" type="Array" setter="_set_default_input_values" getter="_get_default_input_values" override="true" default="[ 0, Vector3( 0, 0, 0 ), 1, Vector3( 0, 0, 0 ), 2, false, 3, 1.0 ]" />
+ <member name="default_input_values" type="Array" setter="_set_default_input_values" getter="_get_default_input_values" override="true" default="[ 2, false, 3, 1.0 ]" />
</members>
<constants>
</constants>
diff --git a/doc/classes/X509Certificate.xml b/doc/classes/X509Certificate.xml
index 50e9e4e0d4..5f3e91c4e6 100644
--- a/doc/classes/X509Certificate.xml
+++ b/doc/classes/X509Certificate.xml
@@ -6,6 +6,7 @@
<description>
The X509Certificate class represents an X509 certificate. Certificates can be loaded and saved like any other [Resource].
They can be used as the server certificate in [method StreamPeerSSL.accept_stream] (along with the proper [CryptoKey]), and to specify the only certificate that should be accepted when connecting to an SSL server via [method StreamPeerSSL.connect_to_stream].
+ [b]Note:[/b] Not available in HTML5 exports.
</description>
<tutorials>
</tutorials>
diff --git a/doc/classes/bool.xml b/doc/classes/bool.xml
index 533963b460..ba6a932d4f 100644
--- a/doc/classes/bool.xml
+++ b/doc/classes/bool.xml
@@ -4,7 +4,38 @@
Boolean built-in type.
</brief_description>
<description>
- Boolean built-in type.
+ Boolean is a built-in type. It can represent any data type that is either a true or false value. You can think of it as an switch with on or off (1 or 0) setting . It's often used as part of programming logic in condition statements like [code]if[/code] statements.
+ [b]Note:[/b] In a code below [code]if can_shoot[/code] is equivalent of [code]if can_shoot == true[/code]. It is good practice to follow the natural spoken language structure when possible. Use [code]if can_shoot[/code] rather than [code]if can_shoot == true[/code] and use [code]if not can_shoot[/code] rather than [code]if can_shoot == false[/code].
+ [codeblock]
+ var can_shoot = true
+
+ func shoot():
+ if can_shoot:
+ # Perform shooting actions here.
+ [/codeblock]
+ The following code will only create a bullet if both conditions are met: action "shoot" is pressed and if [code]can_shoot[/code] is [code]true[/code].
+ [b]Note:[/b] [code]Input.is_action_pressed("shoot")[/code] is also a boolean that is [code]true[/code] when "shoot" is pressed and [code]false[/code] when "shoot" isn't pressed.
+ [codeblock]
+ var can_shoot = true
+
+ func shoot():
+ if can_shoot and Input.is_action_pressed("shoot"):
+ create_bullet()
+ [/codeblock]
+ 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.
+ [codeblock]
+ var can_shoot = true
+ onready var cool_down = $CoolDownTimer
+
+ func shoot():
+ if can_shoot and Input.is_action_pressed("shoot"):
+ create_bullet()
+ can_shoot = false
+ cool_down.start()
+
+ func _on_CoolDownTimer_timeout():
+ can_shoot = true
+ [/codeblock]
</description>
<tutorials>
</tutorials>
diff --git a/doc/classes/float.xml b/doc/classes/float.xml
index 7164e8cb0a..1571bae847 100644
--- a/doc/classes/float.xml
+++ b/doc/classes/float.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="float" category="Built-In Types" version="3.2">
<brief_description>
- Float built-in type
+ Float built-in type.
</brief_description>
<description>
Float built-in type.
diff --git a/doc/tools/makerst.py b/doc/tools/makerst.py
index 91240e9550..4b07bf00ee 100755
--- a/doc/tools/makerst.py
+++ b/doc/tools/makerst.py
@@ -393,15 +393,22 @@ def make_rst_class(class_def, state, dry_run, output_dir): # type: (ClassDef, S
f.write(make_type(child, state))
f.write("\n\n")
- # Category
- if class_def.category is not None:
- f.write('**Category:** ' + class_def.category.strip() + "\n\n")
-
# Brief description
- f.write(make_heading('Brief Description', '-'))
if class_def.brief_description is not None:
f.write(rstize_text(class_def.brief_description.strip(), state) + "\n\n")
+ # Class description
+ if class_def.description is not None and class_def.description.strip() != '':
+ f.write(make_heading('Description', '-'))
+ f.write(rstize_text(class_def.description.strip(), state) + "\n\n")
+
+ # Online tutorials
+ if len(class_def.tutorials) > 0:
+ f.write(make_heading('Tutorials', '-'))
+ for t in class_def.tutorials:
+ link = t.strip()
+ f.write("- " + make_url(link) + "\n\n")
+
# Properties overview
if len(class_def.properties) > 0:
f.write(make_heading('Properties', '-'))
@@ -494,18 +501,6 @@ def make_rst_class(class_def, state, dry_run, output_dir): # type: (ClassDef, S
f.write('\n\n')
- # Class description
- if class_def.description is not None and class_def.description.strip() != '':
- f.write(make_heading('Description', '-'))
- f.write(rstize_text(class_def.description.strip(), state) + "\n\n")
-
- # Online tutorials
- if len(class_def.tutorials) > 0:
- f.write(make_heading('Tutorials', '-'))
- for t in class_def.tutorials:
- link = t.strip()
- f.write("- " + make_url(link) + "\n\n")
-
# Property descriptions
if any(not p.overridden for p in class_def.properties.values()) > 0:
f.write(make_heading('Property Descriptions', '-'))
diff --git a/drivers/dummy/rasterizer_dummy.h b/drivers/dummy/rasterizer_dummy.h
index 167159c7e9..00758a73a4 100644
--- a/drivers/dummy/rasterizer_dummy.h
+++ b/drivers/dummy/rasterizer_dummy.h
@@ -742,6 +742,8 @@ public:
int get_captured_render_info(VS::RenderInfo p_info) { return 0; }
int get_render_info(VS::RenderInfo p_info) { return 0; }
+ String get_video_adapter_name() const { return String(); }
+ String get_video_adapter_vendor() const { return String(); }
static RasterizerStorage *base_singleton;
diff --git a/drivers/gles2/rasterizer_canvas_gles2.cpp b/drivers/gles2/rasterizer_canvas_gles2.cpp
index 10c9846fde..373d3989ce 100644
--- a/drivers/gles2/rasterizer_canvas_gles2.cpp
+++ b/drivers/gles2/rasterizer_canvas_gles2.cpp
@@ -1894,7 +1894,7 @@ void RasterizerCanvasGLES2::canvas_light_shadow_buffer_update(RID p_buffer, cons
while (instance) {
- RasterizerStorageGLES2::CanvasOccluder *cc = storage->canvas_occluder_owner.get(instance->polygon_buffer);
+ RasterizerStorageGLES2::CanvasOccluder *cc = storage->canvas_occluder_owner.getornull(instance->polygon_buffer);
if (!cc || cc->len == 0 || !(p_light_mask & instance->light_mask)) {
instance = instance->next;
diff --git a/drivers/gles2/rasterizer_gles2.cpp b/drivers/gles2/rasterizer_gles2.cpp
index cac124ff5f..c4e9541a36 100644
--- a/drivers/gles2/rasterizer_gles2.cpp
+++ b/drivers/gles2/rasterizer_gles2.cpp
@@ -263,8 +263,7 @@ void RasterizerGLES2::initialize() {
#endif // GLES_OVER_GL
#endif // CAN_DEBUG
- const GLubyte *renderer = glGetString(GL_RENDERER);
- print_line("OpenGL ES 2.0 Renderer: " + String((const char *)renderer));
+ print_line("OpenGL ES 2.0 Renderer: " + VisualServer::get_singleton()->get_video_adapter_name());
storage->initialize();
canvas->initialize();
scene->initialize();
diff --git a/drivers/gles2/rasterizer_scene_gles2.cpp b/drivers/gles2/rasterizer_scene_gles2.cpp
index 5c52d88cc7..6b1574bbbd 100644
--- a/drivers/gles2/rasterizer_scene_gles2.cpp
+++ b/drivers/gles2/rasterizer_scene_gles2.cpp
@@ -1169,7 +1169,7 @@ void RasterizerSceneGLES2::_add_geometry_with_material(RasterizerStorageGLES2::G
LightInstance *li = light_instance_owner.getornull(e->instance->light_instances[i]);
- if (li->light_index >= render_light_instance_count || render_light_instances[li->light_index] != li) {
+ if (!li || li->light_index >= render_light_instance_count || render_light_instances[li->light_index] != li) {
continue; // too many or light_index did not correspond to the light instances to be rendered
}
@@ -3325,6 +3325,7 @@ void RasterizerSceneGLES2::render_scene(const Transform &p_cam_transform, const
glDepthMask(GL_TRUE);
glClearDepth(1.0f);
glEnable(GL_DEPTH_TEST);
+ glClear(GL_DEPTH_BUFFER_BIT);
// clear color
@@ -3351,13 +3352,12 @@ void RasterizerSceneGLES2::render_scene(const Transform &p_cam_transform, const
if (!env || env->bg_mode != VS::ENV_BG_KEEP) {
glClearColor(clear_color.r, clear_color.g, clear_color.b, clear_color.a);
+ glClear(GL_COLOR_BUFFER_BIT);
}
state.default_ambient = Color(clear_color.r, clear_color.g, clear_color.b, 1.0);
state.default_bg = Color(clear_color.r, clear_color.g, clear_color.b, 1.0);
- glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
-
if (storage->frame.current_rt && storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_DIRECT_TO_SCREEN]) {
glDisable(GL_SCISSOR_TEST);
}
diff --git a/drivers/gles2/rasterizer_storage_gles2.cpp b/drivers/gles2/rasterizer_storage_gles2.cpp
index 657148cb40..7980c43517 100644
--- a/drivers/gles2/rasterizer_storage_gles2.cpp
+++ b/drivers/gles2/rasterizer_storage_gles2.cpp
@@ -109,6 +109,7 @@ PFNGLFRAMEBUFFERTEXTURE2DMULTISAMPLEEXTPROC glFramebufferTexture2DMultisampleEXT
#define glFramebufferTexture2DMultisample glFramebufferTexture2DMultisampleANGLE
#endif
+#define GL_TEXTURE_3D 0x806F
#define GL_MAX_SAMPLES 0x8D57
#endif //!GLES_OVER_GL
@@ -565,11 +566,11 @@ void RasterizerStorageGLES2::texture_allocate(RID p_texture, int p_width, int p_
texture->target = GL_TEXTURE_CUBE_MAP;
texture->images.resize(6);
} break;
- case VS::TEXTURE_TYPE_2D_ARRAY: {
- texture->images.resize(p_depth_3d);
- } break;
+ case VS::TEXTURE_TYPE_2D_ARRAY:
case VS::TEXTURE_TYPE_3D: {
- texture->images.resize(p_depth_3d);
+ texture->target = GL_TEXTURE_3D;
+ ERR_PRINT("3D textures and Texture Arrays are not supported in GLES2. Please switch to the GLES3 backend.");
+ return;
} break;
default: {
ERR_PRINT("Unknown texture type!");
@@ -626,6 +627,10 @@ void RasterizerStorageGLES2::texture_set_data(RID p_texture, const Ref<Image> &p
Texture *texture = texture_owner.getornull(p_texture);
ERR_FAIL_COND(!texture);
+ if (texture->target == GL_TEXTURE_3D) {
+ // Target is set to a 3D texture or array texture, exit early to avoid spamming errors
+ return;
+ }
ERR_FAIL_COND(!texture->active);
ERR_FAIL_COND(texture->render_target);
ERR_FAIL_COND(texture->format != p_image->get_format());
@@ -2435,22 +2440,10 @@ void RasterizerStorageGLES2::mesh_add_surface(RID p_mesh, uint32_t p_format, VS:
if (surface->blend_shape_data.size()) {
ERR_PRINT_ONCE("Blend shapes are not supported in OpenGL ES 2.0");
}
- surface->data = array;
- surface->index_data = p_index_array;
-#else
- // Even on non-tools builds, a copy of the surface->data is needed in certain circumstances.
- // Rigged meshes using the USE_SKELETON_SOFTWARE path need to read bone data
- // from surface->data.
-
- // if USE_SKELETON_SOFTWARE is active
- if (config.use_skeleton_software) {
- // if this geometry is used specifically for skinning
- if (p_format & (VS::ARRAY_FORMAT_BONES | VS::ARRAY_FORMAT_WEIGHTS))
- surface->data = array;
- }
- // An alternative is to always make a copy of surface->data.
#endif
+ surface->data = array;
+ surface->index_data = p_index_array;
surface->total_data_size += surface->array_byte_size + surface->index_array_byte_size;
for (int i = 0; i < surface->skeleton_bone_used.size(); i++) {
@@ -2874,20 +2867,20 @@ void RasterizerStorageGLES2::multimesh_allocate(RID p_multimesh, int p_instances
multimesh->xform_floats = 12;
}
- if (multimesh->color_format == VS::MULTIMESH_COLOR_NONE) {
- multimesh->color_floats = 0;
- } else if (multimesh->color_format == VS::MULTIMESH_COLOR_8BIT) {
+ if (multimesh->color_format == VS::MULTIMESH_COLOR_8BIT) {
multimesh->color_floats = 1;
} else if (multimesh->color_format == VS::MULTIMESH_COLOR_FLOAT) {
multimesh->color_floats = 4;
+ } else {
+ multimesh->color_floats = 0;
}
- if (multimesh->custom_data_format == VS::MULTIMESH_CUSTOM_DATA_NONE) {
- multimesh->custom_data_floats = 0;
- } else if (multimesh->custom_data_format == VS::MULTIMESH_CUSTOM_DATA_8BIT) {
+ if (multimesh->custom_data_format == VS::MULTIMESH_CUSTOM_DATA_8BIT) {
multimesh->custom_data_floats = 1;
} else if (multimesh->custom_data_format == VS::MULTIMESH_CUSTOM_DATA_FLOAT) {
multimesh->custom_data_floats = 4;
+ } else {
+ multimesh->custom_data_floats = 0;
}
int format_floats = multimesh->color_floats + multimesh->xform_floats + multimesh->custom_data_floats;
@@ -3063,6 +3056,7 @@ void RasterizerStorageGLES2::multimesh_instance_set_color(RID p_multimesh, int p
ERR_FAIL_COND(!multimesh);
ERR_FAIL_INDEX(p_index, multimesh->size);
ERR_FAIL_COND(multimesh->color_format == VS::MULTIMESH_COLOR_NONE);
+ ERR_FAIL_INDEX(multimesh->color_format, VS::MULTIMESH_COLOR_MAX);
int stride = multimesh->color_floats + multimesh->xform_floats + multimesh->custom_data_floats;
float *dataptr = &multimesh->data.write[stride * p_index + multimesh->xform_floats];
@@ -3095,6 +3089,7 @@ void RasterizerStorageGLES2::multimesh_instance_set_custom_data(RID p_multimesh,
ERR_FAIL_COND(!multimesh);
ERR_FAIL_INDEX(p_index, multimesh->size);
ERR_FAIL_COND(multimesh->custom_data_format == VS::MULTIMESH_CUSTOM_DATA_NONE);
+ ERR_FAIL_INDEX(multimesh->custom_data_format, VS::MULTIMESH_CUSTOM_DATA_MAX);
int stride = multimesh->color_floats + multimesh->xform_floats + multimesh->custom_data_floats;
float *dataptr = &multimesh->data.write[stride * p_index + multimesh->xform_floats + multimesh->color_floats];
@@ -3182,6 +3177,7 @@ Color RasterizerStorageGLES2::multimesh_instance_get_color(RID p_multimesh, int
ERR_FAIL_COND_V(!multimesh, Color());
ERR_FAIL_INDEX_V(p_index, multimesh->size, Color());
ERR_FAIL_COND_V(multimesh->color_format == VS::MULTIMESH_COLOR_NONE, Color());
+ ERR_FAIL_INDEX_V(multimesh->color_format, VS::MULTIMESH_COLOR_MAX, Color());
int stride = multimesh->color_floats + multimesh->xform_floats + multimesh->custom_data_floats;
float *dataptr = &multimesh->data.write[stride * p_index + multimesh->xform_floats];
@@ -3214,6 +3210,7 @@ Color RasterizerStorageGLES2::multimesh_instance_get_custom_data(RID p_multimesh
ERR_FAIL_COND_V(!multimesh, Color());
ERR_FAIL_INDEX_V(p_index, multimesh->size, Color());
ERR_FAIL_COND_V(multimesh->custom_data_format == VS::MULTIMESH_CUSTOM_DATA_NONE, Color());
+ ERR_FAIL_INDEX_V(multimesh->custom_data_format, VS::MULTIMESH_CUSTOM_DATA_MAX, Color());
int stride = multimesh->color_floats + multimesh->xform_floats + multimesh->custom_data_floats;
float *dataptr = &multimesh->data.write[stride * p_index + multimesh->xform_floats + multimesh->color_floats];
@@ -5778,6 +5775,16 @@ int RasterizerStorageGLES2::get_render_info(VS::RenderInfo p_info) {
}
}
+String RasterizerStorageGLES2::get_video_adapter_name() const {
+
+ return (const char *)glGetString(GL_RENDERER);
+}
+
+String RasterizerStorageGLES2::get_video_adapter_vendor() const {
+
+ return (const char *)glGetString(GL_VENDOR);
+}
+
void RasterizerStorageGLES2::initialize() {
RasterizerStorageGLES2::system_fbo = 0;
diff --git a/drivers/gles2/rasterizer_storage_gles2.h b/drivers/gles2/rasterizer_storage_gles2.h
index 62926ce713..83697b9872 100644
--- a/drivers/gles2/rasterizer_storage_gles2.h
+++ b/drivers/gles2/rasterizer_storage_gles2.h
@@ -1307,6 +1307,8 @@ public:
virtual int get_captured_render_info(VS::RenderInfo p_info);
virtual int get_render_info(VS::RenderInfo p_info);
+ virtual String get_video_adapter_name() const;
+ virtual String get_video_adapter_vendor() const;
RasterizerStorageGLES2();
};
diff --git a/drivers/gles2/shader_compiler_gles2.cpp b/drivers/gles2/shader_compiler_gles2.cpp
index fc59486090..24b89aedc2 100644
--- a/drivers/gles2/shader_compiler_gles2.cpp
+++ b/drivers/gles2/shader_compiler_gles2.cpp
@@ -522,9 +522,6 @@ String ShaderCompilerGLES2::_dump_node_code(SL::Node *p_node, int p_level, Gener
SL::ArrayDeclarationNode *arr_dec_node = (SL::ArrayDeclarationNode *)p_node;
StringBuffer<> declaration;
- if (arr_dec_node->is_const) {
- declaration += "const ";
- }
declaration += _prestr(arr_dec_node->precision);
declaration += _typestr(arr_dec_node->datatype);
@@ -540,22 +537,6 @@ String ShaderCompilerGLES2::_dump_node_code(SL::Node *p_node, int p_level, Gener
declaration += "[";
declaration += itos(arr_dec_node->declarations[i].size);
declaration += "]";
- int sz = arr_dec_node->declarations[i].initializer.size();
- if (sz > 0) {
- declaration += "=";
- declaration += _typestr(arr_dec_node->datatype);
- declaration += "[";
- declaration += itos(sz);
- declaration += "]";
- declaration += "(";
- for (int j = 0; j < sz; j++) {
- declaration += _dump_node_code(arr_dec_node->declarations[i].initializer[j], p_level, r_gen_code, p_actions, p_default_actions, p_assigning);
- if (j != sz - 1) {
- declaration += ", ";
- }
- }
- declaration += ")";
- }
}
code += declaration.as_string();
diff --git a/drivers/gles2/shaders/scene.glsl b/drivers/gles2/shaders/scene.glsl
index 63eee4eb87..ac7a8796a3 100644
--- a/drivers/gles2/shaders/scene.glsl
+++ b/drivers/gles2/shaders/scene.glsl
@@ -1666,19 +1666,19 @@ FRAGMENT_SHADER_CODE
#ifdef USE_LIGHTMAP_CAPTURE
{
- vec3 cone_dirs[12] = vec3[](
- vec3(0.0, 0.0, 1.0),
- vec3(0.866025, 0.0, 0.5),
- vec3(0.267617, 0.823639, 0.5),
- vec3(-0.700629, 0.509037, 0.5),
- vec3(-0.700629, -0.509037, 0.5),
- vec3(0.267617, -0.823639, 0.5),
- vec3(0.0, 0.0, -1.0),
- vec3(0.866025, 0.0, -0.5),
- vec3(0.267617, 0.823639, -0.5),
- vec3(-0.700629, 0.509037, -0.5),
- vec3(-0.700629, -0.509037, -0.5),
- vec3(0.267617, -0.823639, -0.5));
+ vec3 cone_dirs[12];
+ cone_dirs[0] = vec3(0.0, 0.0, 1.0);
+ cone_dirs[1] = vec3(0.866025, 0.0, 0.5);
+ cone_dirs[2] = vec3(0.267617, 0.823639, 0.5);
+ cone_dirs[3] = vec3(-0.700629, 0.509037, 0.5);
+ cone_dirs[4] = vec3(-0.700629, -0.509037, 0.5);
+ cone_dirs[5] = vec3(0.267617, -0.823639, 0.5);
+ cone_dirs[6] = vec3(0.0, 0.0, -1.0);
+ cone_dirs[7] = vec3(0.866025, 0.0, -0.5);
+ cone_dirs[8] = vec3(0.267617, 0.823639, -0.5);
+ cone_dirs[9] = vec3(-0.700629, 0.509037, -0.5);
+ cone_dirs[10] = vec3(-0.700629, -0.509037, -0.5);
+ cone_dirs[11] = vec3(0.267617, -0.823639, -0.5);
vec3 local_normal = normalize(camera_matrix * vec4(normal, 0.0)).xyz;
vec4 captured = vec4(0.0);
diff --git a/drivers/gles3/rasterizer_canvas_gles3.cpp b/drivers/gles3/rasterizer_canvas_gles3.cpp
index 55a38c917f..b7b31c66aa 100644
--- a/drivers/gles3/rasterizer_canvas_gles3.cpp
+++ b/drivers/gles3/rasterizer_canvas_gles3.cpp
@@ -1012,6 +1012,7 @@ void RasterizerCanvasGLES3::_canvas_item_render_commands(Item *p_item, Item *cur
switch (multi_mesh->color_format) {
+ case VS::MULTIMESH_COLOR_MAX:
case VS::MULTIMESH_COLOR_NONE: {
glDisableVertexAttribArray(11);
glVertexAttrib4f(11, 1, 1, 1, 1);
@@ -1033,6 +1034,7 @@ void RasterizerCanvasGLES3::_canvas_item_render_commands(Item *p_item, Item *cur
switch (multi_mesh->custom_data_format) {
+ case VS::MULTIMESH_CUSTOM_DATA_MAX:
case VS::MULTIMESH_CUSTOM_DATA_NONE: {
glDisableVertexAttribArray(12);
glVertexAttrib4f(12, 1, 1, 1, 1);
@@ -1889,7 +1891,7 @@ void RasterizerCanvasGLES3::canvas_light_shadow_buffer_update(RID p_buffer, cons
while (instance) {
- RasterizerStorageGLES3::CanvasOccluder *cc = storage->canvas_occluder_owner.get(instance->polygon_buffer);
+ RasterizerStorageGLES3::CanvasOccluder *cc = storage->canvas_occluder_owner.getornull(instance->polygon_buffer);
if (!cc || cc->len == 0 || !(p_light_mask & instance->light_mask)) {
instance = instance->next;
diff --git a/drivers/gles3/rasterizer_gles3.cpp b/drivers/gles3/rasterizer_gles3.cpp
index d428fe33ee..ef2c318807 100644
--- a/drivers/gles3/rasterizer_gles3.cpp
+++ b/drivers/gles3/rasterizer_gles3.cpp
@@ -186,8 +186,7 @@ void RasterizerGLES3::initialize() {
}
*/
- const GLubyte *renderer = glGetString(GL_RENDERER);
- print_line("OpenGL ES 3.0 Renderer: " + String((const char *)renderer));
+ print_line("OpenGL ES 3.0 Renderer: " + VisualServer::get_singleton()->get_video_adapter_name());
storage->initialize();
canvas->initialize();
scene->initialize();
diff --git a/drivers/gles3/rasterizer_scene_gles3.cpp b/drivers/gles3/rasterizer_scene_gles3.cpp
index 3ee39ede18..0ed2637a11 100644
--- a/drivers/gles3/rasterizer_scene_gles3.cpp
+++ b/drivers/gles3/rasterizer_scene_gles3.cpp
@@ -1416,6 +1416,7 @@ void RasterizerSceneGLES3::_setup_geometry(RenderList::Element *e, const Transfo
switch (multi_mesh->color_format) {
+ case VS::MULTIMESH_COLOR_MAX:
case VS::MULTIMESH_COLOR_NONE: {
glDisableVertexAttribArray(11);
glVertexAttrib4f(11, 1, 1, 1, 1);
@@ -1437,6 +1438,7 @@ void RasterizerSceneGLES3::_setup_geometry(RenderList::Element *e, const Transfo
switch (multi_mesh->custom_data_format) {
+ case VS::MULTIMESH_CUSTOM_DATA_MAX:
case VS::MULTIMESH_CUSTOM_DATA_NONE: {
glDisableVertexAttribArray(12);
glVertexAttrib4f(12, 1, 1, 1, 1);
@@ -1887,17 +1889,17 @@ void RasterizerSceneGLES3::_setup_light(RenderList::Element *e, const Transform
const RID *lights = e->instance->light_instances.ptr();
for (int i = 0; i < lc; i++) {
- LightInstance *li = light_instance_owner.getptr(lights[i]);
- if (li->last_pass != render_pass) //not visible
+ LightInstance *li = light_instance_owner.getornull(lights[i]);
+ if (!li || li->last_pass != render_pass) //not visible
continue;
- if (li->light_ptr->type == VS::LIGHT_OMNI) {
+ if (li && li->light_ptr->type == VS::LIGHT_OMNI) {
if (omni_count < maxobj && e->instance->layer_mask & li->light_ptr->cull_mask) {
omni_indices[omni_count++] = li->light_index;
}
}
- if (li->light_ptr->type == VS::LIGHT_SPOT) {
+ if (li && li->light_ptr->type == VS::LIGHT_SPOT) {
if (spot_count < maxobj && e->instance->layer_mask & li->light_ptr->cull_mask) {
spot_indices[spot_count++] = li->light_index;
}
diff --git a/drivers/gles3/rasterizer_storage_gles3.cpp b/drivers/gles3/rasterizer_storage_gles3.cpp
index bf742f4d25..801763609e 100644
--- a/drivers/gles3/rasterizer_storage_gles3.cpp
+++ b/drivers/gles3/rasterizer_storage_gles3.cpp
@@ -4470,20 +4470,20 @@ void RasterizerStorageGLES3::multimesh_allocate(RID p_multimesh, int p_instances
multimesh->xform_floats = 12;
}
- if (multimesh->color_format == VS::MULTIMESH_COLOR_NONE) {
- multimesh->color_floats = 0;
- } else if (multimesh->color_format == VS::MULTIMESH_COLOR_8BIT) {
+ if (multimesh->color_format == VS::MULTIMESH_COLOR_8BIT) {
multimesh->color_floats = 1;
} else if (multimesh->color_format == VS::MULTIMESH_COLOR_FLOAT) {
multimesh->color_floats = 4;
+ } else {
+ multimesh->color_floats = 0;
}
- if (multimesh->custom_data_format == VS::MULTIMESH_CUSTOM_DATA_NONE) {
- multimesh->custom_data_floats = 0;
- } else if (multimesh->custom_data_format == VS::MULTIMESH_CUSTOM_DATA_8BIT) {
+ if (multimesh->custom_data_format == VS::MULTIMESH_CUSTOM_DATA_8BIT) {
multimesh->custom_data_floats = 1;
} else if (multimesh->custom_data_format == VS::MULTIMESH_CUSTOM_DATA_FLOAT) {
multimesh->custom_data_floats = 4;
+ } else {
+ multimesh->custom_data_floats = 0;
}
int format_floats = multimesh->color_floats + multimesh->xform_floats + multimesh->custom_data_floats;
@@ -4679,6 +4679,7 @@ void RasterizerStorageGLES3::multimesh_instance_set_color(RID p_multimesh, int p
ERR_FAIL_COND(!multimesh);
ERR_FAIL_INDEX(p_index, multimesh->size);
ERR_FAIL_COND(multimesh->color_format == VS::MULTIMESH_COLOR_NONE);
+ ERR_FAIL_INDEX(multimesh->color_format, VS::MULTIMESH_COLOR_MAX);
int stride = multimesh->color_floats + multimesh->xform_floats + multimesh->custom_data_floats;
float *dataptr = &multimesh->data.write[stride * p_index + multimesh->xform_floats];
@@ -4712,6 +4713,7 @@ void RasterizerStorageGLES3::multimesh_instance_set_custom_data(RID p_multimesh,
ERR_FAIL_COND(!multimesh);
ERR_FAIL_INDEX(p_index, multimesh->size);
ERR_FAIL_COND(multimesh->custom_data_format == VS::MULTIMESH_CUSTOM_DATA_NONE);
+ ERR_FAIL_INDEX(multimesh->custom_data_format, VS::MULTIMESH_CUSTOM_DATA_MAX);
int stride = multimesh->color_floats + multimesh->xform_floats + multimesh->custom_data_floats;
float *dataptr = &multimesh->data.write[stride * p_index + multimesh->xform_floats + multimesh->color_floats];
@@ -4800,6 +4802,7 @@ Color RasterizerStorageGLES3::multimesh_instance_get_color(RID p_multimesh, int
ERR_FAIL_COND_V(!multimesh, Color());
ERR_FAIL_INDEX_V(p_index, multimesh->size, Color());
ERR_FAIL_COND_V(multimesh->color_format == VS::MULTIMESH_COLOR_NONE, Color());
+ ERR_FAIL_INDEX_V(multimesh->color_format, VS::MULTIMESH_COLOR_MAX, Color());
int stride = multimesh->color_floats + multimesh->xform_floats + multimesh->custom_data_floats;
float *dataptr = &multimesh->data.write[stride * p_index + multimesh->xform_floats];
@@ -4833,6 +4836,7 @@ Color RasterizerStorageGLES3::multimesh_instance_get_custom_data(RID p_multimesh
ERR_FAIL_COND_V(!multimesh, Color());
ERR_FAIL_INDEX_V(p_index, multimesh->size, Color());
ERR_FAIL_COND_V(multimesh->custom_data_format == VS::MULTIMESH_CUSTOM_DATA_NONE, Color());
+ ERR_FAIL_INDEX_V(multimesh->custom_data_format, VS::MULTIMESH_CUSTOM_DATA_MAX, Color());
int stride = multimesh->color_floats + multimesh->xform_floats + multimesh->custom_data_floats;
float *dataptr = &multimesh->data.write[stride * p_index + multimesh->xform_floats + multimesh->color_floats];
@@ -8095,6 +8099,16 @@ int RasterizerStorageGLES3::get_render_info(VS::RenderInfo p_info) {
}
}
+String RasterizerStorageGLES3::get_video_adapter_name() const {
+
+ return (const char *)glGetString(GL_RENDERER);
+}
+
+String RasterizerStorageGLES3::get_video_adapter_vendor() const {
+
+ return (const char *)glGetString(GL_VENDOR);
+}
+
void RasterizerStorageGLES3::initialize() {
RasterizerStorageGLES3::system_fbo = 0;
diff --git a/drivers/gles3/rasterizer_storage_gles3.h b/drivers/gles3/rasterizer_storage_gles3.h
index 833cdb4a94..bd853852fe 100644
--- a/drivers/gles3/rasterizer_storage_gles3.h
+++ b/drivers/gles3/rasterizer_storage_gles3.h
@@ -1467,6 +1467,8 @@ public:
virtual int get_captured_render_info(VS::RenderInfo p_info);
virtual int get_render_info(VS::RenderInfo p_info);
+ virtual String get_video_adapter_name() const;
+ virtual String get_video_adapter_vendor() const;
RasterizerStorageGLES3();
};
diff --git a/drivers/gles3/shaders/cubemap_filter.glsl b/drivers/gles3/shaders/cubemap_filter.glsl
index f94ac8c81c..3f3313c3a7 100644
--- a/drivers/gles3/shaders/cubemap_filter.glsl
+++ b/drivers/gles3/shaders/cubemap_filter.glsl
@@ -309,7 +309,7 @@ void main() {
}
st /= vec2(M_PI * 2.0, M_PI);
- irradiance += texture(source_panorama, st, source_mip_level).rgb * cos(theta) * sin(theta);
+ irradiance += textureLod(source_panorama, st, source_mip_level).rgb * cos(theta) * sin(theta);
num_samples++;
}
}
diff --git a/drivers/unix/os_unix.cpp b/drivers/unix/os_unix.cpp
index 731c089c83..c5eb343cc8 100644
--- a/drivers/unix/os_unix.cpp
+++ b/drivers/unix/os_unix.cpp
@@ -59,6 +59,7 @@
#include <poll.h>
#include <signal.h>
#include <stdarg.h>
+#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/time.h>
@@ -554,23 +555,38 @@ void UnixTerminalLogger::log_error(const char *p_function, const char *p_file, i
else
err_details = p_code;
+ // Disable color codes if stdout is not a TTY.
+ // This prevents Godot from writing ANSI escape codes when redirecting
+ // stdout and stderr to a file.
+ const bool tty = isatty(fileno(stdout));
+ const char *red = tty ? "\E[0;31m" : "";
+ const char *red_bold = tty ? "\E[1;31m" : "";
+ const char *yellow = tty ? "\E[0;33m" : "";
+ const char *yellow_bold = tty ? "\E[1;33m" : "";
+ const char *magenta = tty ? "\E[0;35m" : "";
+ const char *magenta_bold = tty ? "\E[1;35m" : "";
+ const char *cyan = tty ? "\E[0;36m" : "";
+ const char *cyan_bold = tty ? "\E[1;36m" : "";
+ const char *reset = tty ? "\E[0m" : "";
+ const char *bold = tty ? "\E[1m" : "";
+
switch (p_type) {
case ERR_WARNING:
- logf_error("\E[1;33mWARNING: %s: \E[0m\E[1m%s\n", p_function, err_details);
- logf_error("\E[0;33m At: %s:%i.\E[0m\n", p_file, p_line);
+ logf_error("%sWARNING: %s: %s%s%s\n", yellow_bold, p_function, reset, bold, err_details);
+ logf_error("%s At: %s:%i.%s\n", yellow, p_file, p_line, reset);
break;
case ERR_SCRIPT:
- logf_error("\E[1;35mSCRIPT ERROR: %s: \E[0m\E[1m%s\n", p_function, err_details);
- logf_error("\E[0;35m At: %s:%i.\E[0m\n", p_file, p_line);
+ logf_error("%sSCRIPT ERROR: %s: %s%s%s\n", magenta_bold, p_function, reset, bold, err_details);
+ logf_error("%s At: %s:%i.%s\n", magenta, p_file, p_line, reset);
break;
case ERR_SHADER:
- logf_error("\E[1;36mSHADER ERROR: %s: \E[0m\E[1m%s\n", p_function, err_details);
- logf_error("\E[0;36m At: %s:%i.\E[0m\n", p_file, p_line);
+ logf_error("%sSHADER ERROR: %s: %s%s%s\n", cyan_bold, p_function, reset, bold, err_details);
+ logf_error("%s At: %s:%i.%s\n", cyan, p_file, p_line, reset);
break;
case ERR_ERROR:
default:
- logf_error("\E[1;31mERROR: %s: \E[0m\E[1m%s\n", p_function, err_details);
- logf_error("\E[0;31m At: %s:%i.\E[0m\n", p_file, p_line);
+ logf_error("%sERROR: %s: %s%s%s\n", red_bold, p_function, reset, bold, err_details);
+ logf_error("%s At: %s:%i.%s\n", red, p_file, p_line, reset);
break;
}
}
diff --git a/editor/animation_track_editor.cpp b/editor/animation_track_editor.cpp
index cd19ceb868..f6d5312fc7 100644
--- a/editor/animation_track_editor.cpp
+++ b/editor/animation_track_editor.cpp
@@ -3790,8 +3790,9 @@ void AnimationTrackEditor::insert_value_key(const String &p_property, const Vari
value = p_value; //all good
} else {
String tpath = animation->track_get_path(i);
- if (NodePath(tpath.get_basename()) == np) {
- String subindex = tpath.get_extension();
+ int index = tpath.find_last(":");
+ if (NodePath(tpath.substr(0, index + 1)) == np) {
+ String subindex = tpath.substr(index + 1, tpath.length() - index);
value = p_value.get(subindex);
} else {
continue;
diff --git a/editor/code_editor.cpp b/editor/code_editor.cpp
index e5b4cbdda1..4f684c7bdc 100644
--- a/editor/code_editor.cpp
+++ b/editor/code_editor.cpp
@@ -900,7 +900,7 @@ void CodeTextEditor::update_editor_settings() {
text_editor->set_smooth_scroll_enabled(EditorSettings::get_singleton()->get("text_editor/navigation/smooth_scrolling"));
text_editor->set_v_scroll_speed(EditorSettings::get_singleton()->get("text_editor/navigation/v_scroll_speed"));
text_editor->set_draw_minimap(EditorSettings::get_singleton()->get("text_editor/navigation/show_minimap"));
- text_editor->set_minimap_width(EditorSettings::get_singleton()->get("text_editor/navigation/minimap_width"));
+ text_editor->set_minimap_width((int)EditorSettings::get_singleton()->get("text_editor/navigation/minimap_width") * EDSCALE);
text_editor->set_show_line_numbers(EditorSettings::get_singleton()->get("text_editor/appearance/show_line_numbers"));
text_editor->set_line_numbers_zero_padded(EditorSettings::get_singleton()->get("text_editor/appearance/line_numbers_zero_padded"));
text_editor->set_bookmark_gutter_enabled(EditorSettings::get_singleton()->get("text_editor/appearance/show_bookmark_gutter"));
@@ -1184,7 +1184,7 @@ void CodeTextEditor::move_lines_down() {
void CodeTextEditor::_delete_line(int p_line) {
// this is currently intended to be called within delete_lines()
- // so `begin_complex_operation` is ommitted here
+ // so `begin_complex_operation` is omitted here
text_editor->set_line(p_line, "");
if (p_line == 0 && text_editor->get_line_count() > 1) {
text_editor->cursor_set_line(1);
diff --git a/editor/connections_dialog.cpp b/editor/connections_dialog.cpp
index 60058f2f43..1853133bc7 100644
--- a/editor/connections_dialog.cpp
+++ b/editor/connections_dialog.cpp
@@ -127,6 +127,7 @@ void ConnectDialog::ok_pressed() {
}
}
emit_signal("connected");
+ hide();
}
void ConnectDialog::_cancel_pressed() {
@@ -145,7 +146,17 @@ void ConnectDialog::_tree_node_selected() {
return;
dst_path = source->get_path_to(current);
- get_ok()->set_disabled(false);
+ _update_ok_enabled();
+}
+
+/*
+ * Called each time a target node is activated within the target node tree.
+ */
+void ConnectDialog::_tree_item_activated() {
+
+ if (!get_ok()->is_disabled()) {
+ get_ok()->emit_signal("pressed");
+ }
}
/*
@@ -199,6 +210,27 @@ void ConnectDialog::_remove_bind() {
cdbinds->notify_changed();
}
+/*
+ * Enables or disables the connect button. The connect button is enabled if a
+ * node is selected and valid in the selected mode.
+ */
+void ConnectDialog::_update_ok_enabled() {
+
+ Node *target = tree->get_selected();
+
+ if (target == nullptr) {
+ get_ok()->set_disabled(true);
+ return;
+ }
+
+ if (!advanced->is_pressed() && target->get_script().is_null()) {
+ get_ok()->set_disabled(true);
+ return;
+ }
+
+ get_ok()->set_disabled(false);
+}
+
void ConnectDialog::_notification(int p_what) {
if (p_what == NOTIFICATION_ENTER_TREE) {
@@ -211,8 +243,10 @@ void ConnectDialog::_bind_methods() {
ClassDB::bind_method("_advanced_pressed", &ConnectDialog::_advanced_pressed);
ClassDB::bind_method("_cancel", &ConnectDialog::_cancel_pressed);
ClassDB::bind_method("_tree_node_selected", &ConnectDialog::_tree_node_selected);
+ ClassDB::bind_method("_tree_item_activated", &ConnectDialog::_tree_item_activated);
ClassDB::bind_method("_add_bind", &ConnectDialog::_add_bind);
ClassDB::bind_method("_remove_bind", &ConnectDialog::_remove_bind);
+ ClassDB::bind_method("_update_ok_enabled", &ConnectDialog::_update_ok_enabled);
ADD_SIGNAL(MethodInfo("connected"));
}
@@ -280,6 +314,8 @@ bool ConnectDialog::is_editing() const {
*/
void ConnectDialog::init(Connection c, bool bEdit) {
+ set_hide_on_ok(false);
+
source = static_cast<Node *>(c.source);
signal = c.signal;
@@ -287,13 +323,12 @@ void ConnectDialog::init(Connection c, bool bEdit) {
tree->set_marked(source, true);
if (c.target) {
- get_ok()->set_disabled(false);
set_dst_node(static_cast<Node *>(c.target));
set_dst_method(c.method);
- } else {
- get_ok()->set_disabled(true);
}
+ _update_ok_enabled();
+
bool bDeferred = (c.flags & CONNECT_DEFERRED) == CONNECT_DEFERRED;
bool bOneshot = (c.flags & CONNECT_ONESHOT) == CONNECT_ONESHOT;
@@ -336,6 +371,8 @@ void ConnectDialog::_advanced_pressed() {
error_label->set_visible(!_find_first_script(get_tree()->get_edited_scene_root(), get_tree()->get_edited_scene_root()));
}
+ _update_ok_enabled();
+
set_position((get_viewport_rect().size - get_custom_minimum_size()) / 2);
}
@@ -360,7 +397,7 @@ ConnectDialog::ConnectDialog() {
tree = memnew(SceneTreeEditor(false));
tree->set_connecting_signal(true);
- tree->get_scene_tree()->connect("item_activated", this, "_ok");
+ tree->get_scene_tree()->connect("item_activated", this, "_tree_item_activated");
tree->connect("node_selected", this, "_tree_node_selected");
tree->set_connect_to_script_mode(true);
diff --git a/editor/connections_dialog.h b/editor/connections_dialog.h
index 8ef4eddea1..c30413953a 100644
--- a/editor/connections_dialog.h
+++ b/editor/connections_dialog.h
@@ -76,9 +76,11 @@ class ConnectDialog : public ConfirmationDialog {
void ok_pressed();
void _cancel_pressed();
void _tree_node_selected();
+ void _tree_item_activated();
void _add_bind();
void _remove_bind();
void _advanced_pressed();
+ void _update_ok_enabled();
protected:
void _notification(int p_what);
diff --git a/editor/create_dialog.cpp b/editor/create_dialog.cpp
index 7788d6349a..4adb3844bc 100644
--- a/editor/create_dialog.cpp
+++ b/editor/create_dialog.cpp
@@ -58,8 +58,7 @@ void CreateDialog::popup_create(bool p_dont_clear, bool p_replace_mode, const St
while (!f->eof_reached()) {
String l = f->get_line().strip_edges();
String name = l.split(" ")[0];
-
- if (ClassDB::class_exists(name) || ScriptServer::is_global_class(name)) {
+ if ((ClassDB::class_exists(name) || ScriptServer::is_global_class(name)) && !_is_class_disabled_by_feature_profile(name)) {
TreeItem *ti = recent->create_item(root);
ti->set_text(0, l);
ti->set_icon(0, EditorNode::get_singleton()->get_class_icon(l, base_type));
@@ -274,17 +273,7 @@ bool CreateDialog::_is_class_disabled_by_feature_profile(const StringName &p_cla
return false;
}
- StringName class_name = p_class;
-
- while (class_name != StringName()) {
-
- if (profile->is_class_disabled(class_name)) {
- return true;
- }
- class_name = ClassDB::get_parent_class_nocheck(class_name);
- }
-
- return false;
+ return profile->is_class_disabled(p_class);
}
void CreateDialog::select_type(const String &p_type) {
@@ -615,7 +604,7 @@ void CreateDialog::_update_favorite_list() {
for (int i = 0; i < favorite_list.size(); i++) {
String l = favorite_list[i];
String name = l.split(" ")[0];
- if (!(ClassDB::class_exists(name) || ScriptServer::is_global_class(name)))
+ if (!((ClassDB::class_exists(name) || ScriptServer::is_global_class(name)) && !_is_class_disabled_by_feature_profile(name)))
continue;
TreeItem *ti = favorites->create_item(root);
ti->set_text(0, l);
diff --git a/editor/editor_asset_installer.cpp b/editor/editor_asset_installer.cpp
index ea76aad168..86611bd20a 100644
--- a/editor/editor_asset_installer.cpp
+++ b/editor/editor_asset_installer.cpp
@@ -195,7 +195,7 @@ void EditorAssetInstaller::open(const String &p_path, int p_depth) {
String res_path = "res://" + path;
if (FileAccess::exists(res_path)) {
ti->set_custom_color(0, get_color("error_color", "Editor"));
- ti->set_tooltip(0, res_path + " (Already Exists)");
+ ti->set_tooltip(0, vformat(TTR("%s (Already Exists)"), res_path));
ti->set_checked(0, false);
} else {
ti->set_tooltip(0, res_path);
@@ -288,11 +288,11 @@ void EditorAssetInstaller::ok_pressed() {
unzClose(pkg);
if (failed_files.size()) {
- String msg = "The following files failed extraction from package:\n\n";
+ String msg = TTR("The following files failed extraction from package:") + "\n\n";
for (int i = 0; i < failed_files.size(); i++) {
if (i > 15) {
- msg += "\nAnd " + itos(failed_files.size() - i) + " more files.";
+ msg += "\n" + vformat(TTR("And %s more files."), itos(failed_files.size() - i));
break;
}
msg += failed_files[i];
@@ -317,7 +317,7 @@ EditorAssetInstaller::EditorAssetInstaller() {
add_child(vb);
tree = memnew(Tree);
- vb->add_margin_child("Package Contents:", tree, true);
+ vb->add_margin_child(TTR("Package Contents:"), tree, true);
tree->connect("item_edited", this, "_item_edited");
error = memnew(AcceptDialog);
diff --git a/editor/editor_audio_buses.cpp b/editor/editor_audio_buses.cpp
index 07b4a1ea31..365238222f 100644
--- a/editor/editor_audio_buses.cpp
+++ b/editor/editor_audio_buses.cpp
@@ -1290,7 +1290,7 @@ void EditorAudioBuses::_file_dialog_callback(const String &p_string) {
Error err = ResourceSaver::save(p_string, AudioServer::get_singleton()->generate_bus_layout());
if (err != OK) {
- EditorNode::get_singleton()->show_warning("Error saving file: " + p_string);
+ EditorNode::get_singleton()->show_warning(vformat(TTR("Error saving file: %s"), p_string));
return;
}
diff --git a/editor/editor_data.cpp b/editor/editor_data.cpp
index 8ca202a411..0b43fd5ac0 100644
--- a/editor/editor_data.cpp
+++ b/editor/editor_data.cpp
@@ -314,7 +314,7 @@ void EditorData::copy_object_params(Object *p_object) {
for (List<PropertyInfo>::Element *E = pinfo.front(); E; E = E->next()) {
- if (!(E->get().usage & PROPERTY_USAGE_EDITOR))
+ if (!(E->get().usage & PROPERTY_USAGE_EDITOR) || E->get().name == "script" || E->get().name == "scripts")
continue;
PropertyData pd;
diff --git a/editor/editor_export.cpp b/editor/editor_export.cpp
index 72530e23b9..d66b386f93 100644
--- a/editor/editor_export.cpp
+++ b/editor/editor_export.cpp
@@ -32,6 +32,7 @@
#include "core/crypto/crypto_core.h"
#include "core/io/config_file.h"
+#include "core/io/file_access_pack.h" // PACK_HEADER_MAGIC, PACK_FORMAT_VERSION
#include "core/io/resource_loader.h"
#include "core/io/resource_saver.h"
#include "core/io/zip_io.h"
@@ -970,11 +971,12 @@ Error EditorExportPlatform::save_pack(const Ref<EditorExportPreset> &p_preset, c
int64_t pck_start_pos = f->get_position();
- f->store_32(0x43504447); //GDPC
- f->store_32(1); //pack version
+ f->store_32(PACK_HEADER_MAGIC);
+ f->store_32(PACK_FORMAT_VERSION);
f->store_32(VERSION_MAJOR);
f->store_32(VERSION_MINOR);
- f->store_32(0); //hmph
+ f->store_32(VERSION_PATCH);
+
for (int i = 0; i < 16; i++) {
//reserved
f->store_32(0);
@@ -1049,7 +1051,7 @@ Error EditorExportPlatform::save_pack(const Ref<EditorExportPreset> &p_preset, c
int64_t pck_size = f->get_position() - pck_start_pos;
f->store_64(pck_size);
- f->store_32(0x43504447); //GDPC
+ f->store_32(PACK_HEADER_MAGIC);
if (r_embedded_size) {
*r_embedded_size = f->get_position() - embed_pos;
@@ -1483,41 +1485,29 @@ Ref<Texture> EditorExportPlatformPC::get_logo() const {
bool EditorExportPlatformPC::can_export(const Ref<EditorExportPreset> &p_preset, String &r_error, bool &r_missing_templates) const {
String err;
- bool valid = true;
- bool use64 = p_preset->get("binary_format/64_bits");
-
- if (use64 && (!exists_export_template(debug_file_64, &err) || !exists_export_template(release_file_64, &err))) {
- valid = false;
- }
-
- if (!use64 && (!exists_export_template(debug_file_32, &err) || !exists_export_template(release_file_32, &err))) {
- valid = false;
- }
+ bool valid = false;
- String custom_debug_binary = p_preset->get("custom_template/debug");
- String custom_release_binary = p_preset->get("custom_template/release");
+ // Look for export templates (first official, and if defined custom templates).
- if (custom_debug_binary == "" && custom_release_binary == "") {
- if (!err.empty())
- r_error = err;
- r_missing_templates = !valid;
- return valid;
- }
-
- bool dvalid = true;
- bool rvalid = true;
+ bool use64 = p_preset->get("binary_format/64_bits");
+ bool dvalid = exists_export_template(use64 ? debug_file_64 : debug_file_32, &err);
+ bool rvalid = exists_export_template(use64 ? release_file_64 : release_file_32, &err);
- if (!FileAccess::exists(custom_debug_binary)) {
- dvalid = false;
- err += TTR("Custom debug template not found.") + "\n";
+ if (p_preset->get("custom_template/debug") != "") {
+ dvalid = FileAccess::exists(p_preset->get("custom_template/debug"));
+ if (!dvalid) {
+ err += TTR("Custom debug template not found.") + "\n";
+ }
}
-
- if (!FileAccess::exists(custom_release_binary)) {
- rvalid = false;
- err += TTR("Custom release template not found.") + "\n";
+ if (p_preset->get("custom_template/release") != "") {
+ rvalid = FileAccess::exists(p_preset->get("custom_template/release"));
+ if (!rvalid) {
+ err += TTR("Custom release template not found.") + "\n";
+ }
}
valid = dvalid || rvalid;
+ r_missing_templates = !valid;
if (!err.empty())
r_error = err;
@@ -1598,7 +1588,7 @@ Error EditorExportPlatformPC::export_project(const Ref<EditorExportPreset> &p_pr
if (embedded_size >= 0x100000000 && !p_preset->get("binary_format/64_bits")) {
EditorNode::get_singleton()->show_warning(TTR("On 32-bit exports the embedded PCK cannot be bigger than 4 GiB."));
- return ERR_UNAVAILABLE;
+ return ERR_INVALID_PARAMETER;
}
FixUpEmbeddedPckFunc fixup_func = get_fixup_embedded_pck_func();
diff --git a/editor/editor_feature_profile.cpp b/editor/editor_feature_profile.cpp
index 1fa2bfcd60..a4a7a0cd45 100644
--- a/editor/editor_feature_profile.cpp
+++ b/editor/editor_feature_profile.cpp
@@ -64,7 +64,10 @@ void EditorFeatureProfile::set_disable_class(const StringName &p_class, bool p_d
}
bool EditorFeatureProfile::is_class_disabled(const StringName &p_class) const {
- return disabled_classes.has(p_class);
+ if (p_class == StringName()) {
+ return false;
+ }
+ return disabled_classes.has(p_class) || is_class_disabled(ClassDB::get_parent_class_nocheck(p_class));
}
void EditorFeatureProfile::set_disable_class_editor(const StringName &p_class, bool p_disabled) {
@@ -76,7 +79,10 @@ void EditorFeatureProfile::set_disable_class_editor(const StringName &p_class, b
}
bool EditorFeatureProfile::is_class_editor_disabled(const StringName &p_class) const {
- return disabled_editors.has(p_class);
+ if (p_class == StringName()) {
+ return false;
+ }
+ return disabled_editors.has(p_class) || is_class_editor_disabled(ClassDB::get_parent_class_nocheck(p_class));
}
void EditorFeatureProfile::set_disable_class_property(const StringName &p_class, const StringName &p_property, bool p_disabled) {
diff --git a/editor/editor_help.cpp b/editor/editor_help.cpp
index a0c106441a..53c1d334d2 100644
--- a/editor/editor_help.cpp
+++ b/editor/editor_help.cpp
@@ -418,10 +418,10 @@ void EditorHelp::_update_doc() {
}
}
- if (found)
+ if (found) {
class_desc->pop();
-
- class_desc->add_newline();
+ class_desc->add_newline();
+ }
}
class_desc->add_newline();
@@ -430,9 +430,26 @@ void EditorHelp::_update_doc() {
// Brief description
if (cd.brief_description != "") {
+ class_desc->push_color(text_color);
+ class_desc->push_font(doc_bold_font);
+ class_desc->push_indent(1);
+ _add_text(cd.brief_description);
+ class_desc->pop();
+ class_desc->pop();
+ class_desc->pop();
+ class_desc->add_newline();
+ class_desc->add_newline();
+ class_desc->add_newline();
+ }
+
+ // Class description
+ if (cd.description != "") {
+
+ section_line.push_back(Pair<String, int>(TTR("Description"), class_desc->get_line_count() - 2));
+ description_line = class_desc->get_line_count() - 2;
class_desc->push_color(title_color);
class_desc->push_font(doc_title_font);
- class_desc->add_text(TTR("Brief Description"));
+ class_desc->add_text(TTR("Description"));
class_desc->pop();
class_desc->pop();
@@ -441,11 +458,51 @@ void EditorHelp::_update_doc() {
class_desc->push_color(text_color);
class_desc->push_font(doc_font);
class_desc->push_indent(1);
- _add_text(cd.brief_description);
+ _add_text(cd.description);
+ class_desc->pop();
class_desc->pop();
class_desc->pop();
+ class_desc->add_newline();
+ class_desc->add_newline();
+ class_desc->add_newline();
+ }
+
+ // Online tutorials
+ {
+ class_desc->push_color(title_color);
+ class_desc->push_font(doc_title_font);
+ class_desc->add_text(TTR("Online Tutorials"));
+ class_desc->pop();
class_desc->pop();
+ class_desc->push_indent(1);
+
+ class_desc->push_font(doc_code_font);
+
class_desc->add_newline();
+ // class_desc->add_newline();
+
+ if (cd.tutorials.size() != 0) {
+
+ for (int i = 0; i < cd.tutorials.size(); i++) {
+ String link = cd.tutorials[i];
+ String linktxt = link;
+ int seppos = linktxt.find("//");
+ if (seppos != -1) {
+ linktxt = link.right(seppos + 2);
+ }
+
+ class_desc->push_color(symbol_color);
+ class_desc->append_bbcode("[url=" + link + "]" + linktxt + "[/url]");
+ class_desc->pop();
+ class_desc->add_newline();
+ }
+ } else {
+ class_desc->push_color(comment_color);
+ class_desc->append_bbcode(TTR("There are currently no tutorials for this class, you can [color=$color][url=$url]contribute one[/url][/color] or [color=$color][url=$url2]request one[/url][/color].").replace("$url2", REQUEST_URL).replace("$url", CONTRIBUTE2_URL).replace("$color", link_color_text));
+ class_desc->pop();
+ }
+ class_desc->pop();
+ class_desc->pop();
class_desc->add_newline();
class_desc->add_newline();
}
@@ -922,71 +979,6 @@ void EditorHelp::_update_doc() {
}
}
- // Class description
- if (cd.description != "") {
-
- section_line.push_back(Pair<String, int>(TTR("Class Description"), class_desc->get_line_count() - 2));
- description_line = class_desc->get_line_count() - 2;
- class_desc->push_color(title_color);
- class_desc->push_font(doc_title_font);
- class_desc->add_text(TTR("Class Description"));
- class_desc->pop();
- class_desc->pop();
-
- class_desc->add_newline();
- class_desc->add_newline();
- class_desc->push_color(text_color);
- class_desc->push_font(doc_font);
- class_desc->push_indent(1);
- _add_text(cd.description);
- class_desc->pop();
- class_desc->pop();
- class_desc->pop();
- class_desc->add_newline();
- class_desc->add_newline();
- class_desc->add_newline();
- }
-
- // Online tutorials
- {
- class_desc->push_color(title_color);
- class_desc->push_font(doc_title_font);
- class_desc->add_text(TTR("Online Tutorials"));
- class_desc->pop();
- class_desc->pop();
- class_desc->push_indent(1);
-
- class_desc->push_font(doc_code_font);
-
- class_desc->add_newline();
- // class_desc->add_newline();
-
- if (cd.tutorials.size() != 0) {
-
- for (int i = 0; i < cd.tutorials.size(); i++) {
- String link = cd.tutorials[i];
- String linktxt = link;
- int seppos = linktxt.find("//");
- if (seppos != -1) {
- linktxt = link.right(seppos + 2);
- }
-
- class_desc->push_color(symbol_color);
- class_desc->append_bbcode("[url=" + link + "]" + linktxt + "[/url]");
- class_desc->pop();
- class_desc->add_newline();
- }
- } else {
- class_desc->push_color(comment_color);
- class_desc->append_bbcode(TTR("There are currently no tutorials for this class, you can [color=$color][url=$url]contribute one[/url][/color] or [color=$color][url=$url2]request one[/url][/color].").replace("$url2", REQUEST_URL).replace("$url", CONTRIBUTE2_URL).replace("$color", link_color_text));
- class_desc->pop();
- }
- class_desc->pop();
- class_desc->pop();
- class_desc->add_newline();
- class_desc->add_newline();
- }
-
// Property descriptions
if (property_descr) {
diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp
index 8e6668bc89..c5b67eb971 100644
--- a/editor/editor_node.cpp
+++ b/editor/editor_node.cpp
@@ -369,6 +369,19 @@ void EditorNode::_notification(int p_what) {
case NOTIFICATION_READY: {
+ {
+ _initializing_addons = true;
+ Vector<String> addons;
+ if (ProjectSettings::get_singleton()->has_setting("editor_plugins/enabled")) {
+ addons = ProjectSettings::get_singleton()->get("editor_plugins/enabled");
+ }
+
+ for (int i = 0; i < addons.size(); i++) {
+ set_addon_plugin_enabled(addons[i], true);
+ }
+ _initializing_addons = false;
+ }
+
VisualServer::get_singleton()->viewport_set_hide_scenario(get_scene_root()->get_viewport_rid(), true);
VisualServer::get_singleton()->viewport_set_hide_canvas(get_scene_root()->get_viewport_rid(), true);
VisualServer::get_singleton()->viewport_set_disable_environment(get_viewport()->get_viewport_rid(), true);
@@ -562,46 +575,65 @@ void EditorNode::_fs_changed() {
_mark_unsaved_scenes();
+ // FIXME: Move this to a cleaner location, it's hacky to do this is _fs_changed.
+ String export_error;
if (export_defer.preset != "" && !EditorFileSystem::get_singleton()->is_scanning()) {
+ String preset_name = export_defer.preset;
+ // Ensures export_project does not loop infinitely, because notifications may
+ // come during the export.
+ export_defer.preset = "";
Ref<EditorExportPreset> preset;
for (int i = 0; i < EditorExport::get_singleton()->get_export_preset_count(); ++i) {
preset = EditorExport::get_singleton()->get_export_preset(i);
- if (preset->get_name() == export_defer.preset) {
+ if (preset->get_name() == preset_name) {
break;
}
preset.unref();
}
if (preset.is_null()) {
- String errstr = "Unknown export preset: " + export_defer.preset;
- ERR_PRINTS(errstr);
- OS::get_singleton()->set_exit_code(EXIT_FAILURE);
+ export_error = vformat("Invalid export preset name: %s.", preset_name);
} else {
Ref<EditorExportPlatform> platform = preset->get_platform();
if (platform.is_null()) {
- String errstr = "Preset \"" + export_defer.preset + "\" doesn't have a platform.";
- ERR_PRINTS(errstr);
- OS::get_singleton()->set_exit_code(EXIT_FAILURE);
+ export_error = vformat("Export preset '%s' doesn't have a matching platform.", preset_name);
} else {
- // ensures export_project does not loop infinitely, because notifications may
- // come during the export
- export_defer.preset = "";
Error err = OK;
- if (export_defer.path.ends_with(".pck") || export_defer.path.ends_with(".zip")) {
+ if (export_defer.pack_only) { // Only export .pck or .zip data pack.
if (export_defer.path.ends_with(".zip")) {
err = platform->export_zip(preset, export_defer.debug, export_defer.path);
} else if (export_defer.path.ends_with(".pck")) {
err = platform->export_pack(preset, export_defer.debug, export_defer.path);
}
- } else {
- err = platform->export_project(preset, export_defer.debug, export_defer.path);
+ } else { // Normal project export.
+ String config_error;
+ bool missing_templates;
+ if (!platform->can_export(preset, config_error, missing_templates)) {
+ ERR_PRINT(vformat("Cannot export project with preset '%s' due to configuration errors:\n%s", preset_name, config_error));
+ err = missing_templates ? ERR_FILE_NOT_FOUND : ERR_UNCONFIGURED;
+ } else {
+ err = platform->export_project(preset, export_defer.debug, export_defer.path);
+ }
}
- if (err != OK) {
- ERR_PRINTS(vformat(TTR("Project export failed with error code %d."), (int)err));
- OS::get_singleton()->set_exit_code(EXIT_FAILURE);
+ switch (err) {
+ case OK:
+ break;
+ case ERR_FILE_NOT_FOUND:
+ export_error = vformat("Project export failed for preset '%s', the export template appears to be missing.", preset_name);
+ break;
+ case ERR_FILE_BAD_PATH:
+ export_error = vformat("Project export failed for preset '%s', the target path '%s' appears to be invalid.", preset_name, export_defer.path);
+ break;
+ default:
+ export_error = vformat("Project export failed with error code %d for preset '%s'.", (int)err, preset_name);
+ break;
}
}
}
+ if (!export_error.empty()) {
+ ERR_PRINT(export_error);
+ OS::get_singleton()->set_exit_code(EXIT_FAILURE);
+ }
_exit_editor();
}
}
@@ -641,12 +673,14 @@ void EditorNode::_sources_changed(bool p_exist) {
if (waiting_for_first_scan) {
waiting_for_first_scan = false;
- EditorResourcePreview::get_singleton()->start(); //start previes now that it's safe
+ // Start preview thread now that it's safe.
+ if (!singleton->cmdline_export_mode) {
+ EditorResourcePreview::get_singleton()->start();
+ }
_load_docks();
if (defer_load_scene != "") {
-
load_scene(defer_load_scene);
defer_load_scene = "";
}
@@ -1136,7 +1170,10 @@ void EditorNode::_save_scene_with_preview(String p_file, int p_idx) {
save.step(TTR("Saving Scene"), 4);
_save_scene(p_file, p_idx);
- EditorResourcePreview::get_singleton()->check_for_invalidation(p_file);
+
+ if (!singleton->cmdline_export_mode) {
+ EditorResourcePreview::get_singleton()->check_for_invalidation(p_file);
+ }
}
bool EditorNode::_validate_scene_recursive(const String &p_filename, Node *p_node) {
@@ -3820,7 +3857,7 @@ Ref<Texture> EditorNode::get_class_icon(const String &p_class, const String &p_f
void EditorNode::progress_add_task(const String &p_task, const String &p_label, int p_steps, bool p_can_cancel) {
- if (singleton->disable_progress_dialog) {
+ if (singleton->cmdline_export_mode) {
print_line(p_task + ": begin: " + p_label + " steps: " + itos(p_steps));
} else {
singleton->progress_dialog->add_task(p_task, p_label, p_steps, p_can_cancel);
@@ -3829,7 +3866,7 @@ void EditorNode::progress_add_task(const String &p_task, const String &p_label,
bool EditorNode::progress_task_step(const String &p_task, const String &p_state, int p_step, bool p_force_refresh) {
- if (singleton->disable_progress_dialog) {
+ if (singleton->cmdline_export_mode) {
print_line("\t" + p_task + ": step " + itos(p_step) + ": " + p_state);
return false;
} else {
@@ -3840,7 +3877,7 @@ bool EditorNode::progress_task_step(const String &p_task, const String &p_state,
void EditorNode::progress_end_task(const String &p_task) {
- if (singleton->disable_progress_dialog) {
+ if (singleton->cmdline_export_mode) {
print_line(p_task + ": end");
} else {
singleton->progress_dialog->end_task(p_task);
@@ -3920,13 +3957,13 @@ void EditorNode::_editor_file_dialog_unregister(EditorFileDialog *p_dialog) {
Vector<EditorNodeInitCallback> EditorNode::_init_callbacks;
-Error EditorNode::export_preset(const String &p_preset, const String &p_path, bool p_debug, const String &p_password, bool p_quit_after) {
+Error EditorNode::export_preset(const String &p_preset, const String &p_path, bool p_debug, bool p_pack_only) {
export_defer.preset = p_preset;
export_defer.path = p_path;
export_defer.debug = p_debug;
- export_defer.password = p_password;
- disable_progress_dialog = true;
+ export_defer.pack_only = p_pack_only;
+ cmdline_export_mode = true;
return OK;
}
@@ -5060,6 +5097,7 @@ void EditorNode::_global_menu_action(const Variant &p_id, const Variant &p_meta)
if (id == GLOBAL_NEW_WINDOW) {
if (OS::get_singleton()->get_main_loop()) {
List<String> args;
+ args.push_back("-e");
String exec = OS::get_singleton()->get_executable_path();
OS::ProcessID pid = 0;
@@ -5567,7 +5605,7 @@ EditorNode::EditorNode() {
_initializing_addons = false;
docks_visible = true;
restoring_scenes = false;
- disable_progress_dialog = false;
+ cmdline_export_mode = false;
scene_distraction = false;
script_distraction = false;
@@ -6531,12 +6569,6 @@ EditorNode::EditorNode() {
gui_base->add_child(file);
file->set_current_dir("res://");
- file_export = memnew(EditorFileDialog);
- file_export->set_access(EditorFileDialog::ACCESS_FILESYSTEM);
- gui_base->add_child(file_export);
- file_export->set_title(TTR("Export Project"));
- file_export->connect("file_selected", this, "_dialog_action");
-
file_export_lib = memnew(EditorFileDialog);
file_export_lib->set_title(TTR("Export Library"));
file_export_lib->set_mode(EditorFileDialog::MODE_SAVE_FILE);
@@ -6547,11 +6579,6 @@ EditorNode::EditorNode() {
file_export_lib->get_vbox()->add_child(file_export_lib_merge);
gui_base->add_child(file_export_lib);
- file_export_password = memnew(LineEdit);
- file_export_password->set_secret(true);
- file_export_password->set_editable(false);
- file_export->get_vbox()->add_margin_child(TTR("Password:"), file_export_password);
-
file_script = memnew(EditorFileDialog);
file_script->set_title(TTR("Open & Run a Script"));
file_script->set_access(EditorFileDialog::ACCESS_FILESYSTEM);
@@ -6767,19 +6794,6 @@ EditorNode::EditorNode() {
import_dock->initialize_import_options();
- {
- _initializing_addons = true;
- Vector<String> addons;
- if (ProjectSettings::get_singleton()->has_setting("editor_plugins/enabled")) {
- addons = ProjectSettings::get_singleton()->get("editor_plugins/enabled");
- }
-
- for (int i = 0; i < addons.size(); i++) {
- set_addon_plugin_enabled(addons[i], true);
- }
- _initializing_addons = false;
- }
-
FileAccess::set_file_close_fail_notify_callback(_file_access_close_error_notify);
waiting_for_first_scan = true;
diff --git a/editor/editor_node.h b/editor/editor_node.h
index acff91790d..a5c04d3531 100644
--- a/editor/editor_node.h
+++ b/editor/editor_node.h
@@ -325,18 +325,13 @@ private:
ExportTemplateManager *export_template_manager;
EditorFeatureProfileManager *feature_profile_manager;
EditorFileDialog *file_templates;
- EditorFileDialog *file_export;
EditorFileDialog *file_export_lib;
EditorFileDialog *file_script;
CheckBox *file_export_lib_merge;
- LineEdit *file_export_password;
String current_path;
MenuButton *update_spinner;
String defer_load_scene;
- String defer_export;
- String defer_export_platform;
- bool defer_export_debug;
Node *_last_instanced_scene;
EditorLog *log;
@@ -563,11 +558,10 @@ private:
String preset;
String path;
bool debug;
- String password;
-
+ bool pack_only;
} export_defer;
- bool disable_progress_dialog;
+ bool cmdline_export_mode;
static EditorNode *singleton;
@@ -786,7 +780,7 @@ public:
void _copy_warning(const String &p_str);
- Error export_preset(const String &p_preset, const String &p_path, bool p_debug, const String &p_password, bool p_quit_after = false);
+ Error export_preset(const String &p_preset, const String &p_path, bool p_debug, bool p_pack_only);
static void register_editor_types();
static void unregister_editor_types();
diff --git a/editor/editor_properties.cpp b/editor/editor_properties.cpp
index c049096c35..c134786b89 100644
--- a/editor/editor_properties.cpp
+++ b/editor/editor_properties.cpp
@@ -805,10 +805,10 @@ EditorPropertyLayers::EditorPropertyLayers() {
///////////////////// INT /////////////////////////
-void EditorPropertyInteger::_value_changed(double val) {
+void EditorPropertyInteger::_value_changed(int64_t val) {
if (setting)
return;
- emit_changed(get_edited_property(), (int64_t)val);
+ emit_changed(get_edited_property(), val);
}
void EditorPropertyInteger::update_property() {
@@ -816,14 +816,19 @@ void EditorPropertyInteger::update_property() {
setting = true;
spin->set_value(val);
setting = false;
+#ifdef DEBUG_ENABLED
+ // If spin (currently EditorSplinSlider : Range) is changed so that it can use int64_t, then the below warning wouldn't be a problem.
+ if (val != (int64_t)(double)(val)) {
+ WARN_PRINT("Cannot reliably represent '" + itos(val) + "' in the inspector, value is too large.");
+ }
+#endif
}
void EditorPropertyInteger::_bind_methods() {
-
ClassDB::bind_method(D_METHOD("_value_changed"), &EditorPropertyInteger::_value_changed);
}
-void EditorPropertyInteger::setup(int p_min, int p_max, int p_step, bool p_allow_greater, bool p_allow_lesser) {
+void EditorPropertyInteger::setup(int64_t p_min, int64_t p_max, int64_t p_step, bool p_allow_greater, bool p_allow_lesser) {
spin->set_min(p_min);
spin->set_max(p_max);
spin->set_step(p_step);
diff --git a/editor/editor_properties.h b/editor/editor_properties.h
index 4c7358597e..1853a6b6e1 100644
--- a/editor/editor_properties.h
+++ b/editor/editor_properties.h
@@ -263,14 +263,14 @@ class EditorPropertyInteger : public EditorProperty {
GDCLASS(EditorPropertyInteger, EditorProperty);
EditorSpinSlider *spin;
bool setting;
- void _value_changed(double p_val);
+ void _value_changed(int64_t p_val);
protected:
static void _bind_methods();
public:
virtual void update_property();
- void setup(int p_min, int p_max, int p_step, bool p_allow_greater, bool p_allow_lesser);
+ void setup(int64_t p_min, int64_t p_max, int64_t p_step, bool p_allow_greater, bool p_allow_lesser);
EditorPropertyInteger();
};
diff --git a/editor/editor_resource_preview.cpp b/editor/editor_resource_preview.cpp
index 9d31e26086..f63d4884e2 100644
--- a/editor/editor_resource_preview.cpp
+++ b/editor/editor_resource_preview.cpp
@@ -215,7 +215,6 @@ void EditorResourcePreview::_generate_preview(Ref<ImageTexture> &r_texture, Ref<
void EditorResourcePreview::_thread() {
-#ifndef SERVER_ENABLED
exited = false;
while (!exit) {
@@ -349,7 +348,6 @@ void EditorResourcePreview::_thread() {
preview_mutex->unlock();
}
}
-#endif
exited = true;
}
diff --git a/editor/editor_themes.cpp b/editor/editor_themes.cpp
index 15fb6a9521..2cacc767c8 100644
--- a/editor/editor_themes.cpp
+++ b/editor/editor_themes.cpp
@@ -1012,6 +1012,8 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
theme->set_color("grid_major", "GraphEdit", Color(0.0, 0.0, 0.0, 0.15));
theme->set_color("grid_minor", "GraphEdit", Color(0.0, 0.0, 0.0, 0.07));
}
+ theme->set_color("selection_fill", "GraphEdit", theme->get_color("box_selection_fill_color", "Editor"));
+ theme->set_color("selection_stroke", "GraphEdit", theme->get_color("box_selection_stroke_color", "Editor"));
theme->set_color("activity", "GraphEdit", accent_color);
theme->set_icon("minus", "GraphEdit", theme->get_icon("ZoomLess", "EditorIcons"));
theme->set_icon("more", "GraphEdit", theme->get_icon("ZoomMore", "EditorIcons"));
diff --git a/editor/filesystem_dock.cpp b/editor/filesystem_dock.cpp
index 1fecdfe555..62effb406d 100644
--- a/editor/filesystem_dock.cpp
+++ b/editor/filesystem_dock.cpp
@@ -90,6 +90,7 @@ bool FileSystemDock::_create_tree(TreeItem *p_parent, EditorFileSystemDirectory
// Create all items for the files in the subdirectory.
if (display_mode == DISPLAY_MODE_TREE_ONLY) {
+ String main_scene = ProjectSettings::get_singleton()->get("application/run/main_scene");
for (int i = 0; i < p_dir->get_file_count(); i++) {
String file_type = p_dir->get_file_type(i);
@@ -119,7 +120,6 @@ bool FileSystemDock::_create_tree(TreeItem *p_parent, EditorFileSystemDirectory
file_item->select(0);
file_item->set_as_cursor(0);
}
- String main_scene = ProjectSettings::get_singleton()->get("application/run/main_scene");
if (main_scene == file_metadata) {
file_item->set_custom_color(0, get_color("accent_color", "Editor"));
}
@@ -140,6 +140,7 @@ bool FileSystemDock::_create_tree(TreeItem *p_parent, EditorFileSystemDirectory
subdirectory_item->set_collapsed(false);
} else if (dname != "res://") {
subdirectory_item->get_parent()->remove_child(subdirectory_item);
+ memdelete(subdirectory_item);
}
}
@@ -750,6 +751,7 @@ void FileSystemDock::_update_file_list(bool p_keep_selection) {
}
// Fills the ItemList control node from the FileInfos.
+ String main_scene = ProjectSettings::get_singleton()->get("application/run/main_scene");
String oi = "Object";
for (List<FileInfo>::Element *E = filelist.front(); E; E = E->next()) {
FileInfo *finfo = &(E->get());
@@ -786,6 +788,10 @@ void FileSystemDock::_update_file_list(bool p_keep_selection) {
files->set_item_metadata(item_index, fpath);
}
+ if (fpath == main_scene) {
+ files->set_item_custom_fg_color(item_index, get_color("accent_color", "Editor"));
+ }
+
// Generate the preview.
if (!finfo->import_broken) {
Array udata;
@@ -1584,6 +1590,7 @@ void FileSystemDock::_file_option(int p_option, const Vector<String> &p_selected
ProjectSettings::get_singleton()->set("application/run/main_scene", p_selected[0]);
ProjectSettings::get_singleton()->save();
_update_tree(_compute_uncollapsed_paths());
+ _update_file_list(true);
}
} break;
@@ -1755,8 +1762,8 @@ void FileSystemDock::_file_option(int p_option, const Vector<String> &p_selected
if (!fpath.ends_with("/")) {
fpath = fpath.get_base_dir();
}
- make_script_dialog->config("Node", fpath.plus_file("new_script.gd"), false);
- make_script_dialog->popup_centered(Size2(300, 300) * EDSCALE);
+ make_script_dialog->config("Node", fpath.plus_file("new_script.gd"), false, false);
+ make_script_dialog->popup_centered();
} break;
case FILE_COPY_PATH: {
diff --git a/editor/groups_editor.cpp b/editor/groups_editor.cpp
index c19bee321a..83259afb35 100644
--- a/editor/groups_editor.cpp
+++ b/editor/groups_editor.cpp
@@ -215,7 +215,7 @@ void GroupDialog::_group_renamed() {
return;
}
- String name = renamed_group->get_text(0).strip_edges();
+ const String name = renamed_group->get_text(0).strip_edges();
for (TreeItem *E = groups_root->get_children(); E; E = E->get_next()) {
if (E != renamed_group && E->get_text(0) == name) {
renamed_group->set_text(0, selected_group);
@@ -232,6 +232,8 @@ void GroupDialog::_group_renamed() {
return;
}
+ renamed_group->set_text(0, name); // Spaces trimmed.
+
undo_redo->create_action(TTR("Rename Group"));
List<Node *> nodes;
@@ -254,8 +256,8 @@ void GroupDialog::_group_renamed() {
undo_redo->add_undo_method(this, "_delete_group_item", selected_group);
}
- undo_redo->add_do_method(this, "_rename_group_item", selected_group, renamed_group->get_text(0));
- undo_redo->add_undo_method(this, "_rename_group_item", renamed_group->get_text(0), selected_group);
+ undo_redo->add_do_method(this, "_rename_group_item", selected_group, name);
+ undo_redo->add_undo_method(this, "_rename_group_item", name, selected_group);
undo_redo->add_do_method(this, "_group_selected");
undo_redo->add_undo_method(this, "_group_selected");
undo_redo->add_do_method(this, "emit_signal", "group_edited");
@@ -550,8 +552,8 @@ void GroupsEditor::_add_group(const String &p_group) {
if (!node)
return;
- String name = group_name->get_text();
- if (name.strip_edges() == "")
+ const String name = group_name->get_text().strip_edges();
+ if (name.empty())
return;
if (node->is_in_group(name))
diff --git a/editor/icons/icon_audio_stream_o_g_g_vorbis.svg b/editor/icons/icon_audio_stream_o_g_g_vorbis.svg
new file mode 100644
index 0000000000..a8d6fb6bf1
--- /dev/null
+++ b/editor/icons/icon_audio_stream_o_g_g_vorbis.svg
@@ -0,0 +1 @@
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><linearGradient id="a" gradientUnits="userSpaceOnUse" x1="8" x2="8" y1="1" y2="15"><stop offset="0" stop-color="#ff7a7a"/><stop offset=".5" stop-color="#e1dc7a"/><stop offset="1" stop-color="#66ff9e"/></linearGradient><path d="m11.971 1.002c-.08326.00207-.16593.014541-.24609.037109l-7 2c-.42881.12287-.7244.51487-.72461.96094v5.5508c-.16454-.033679-.33205-.050692-.5-.050781-1.3807 0-2.5 1.1193-2.5 2.5-.00000475 1.3807 1.1193 2.5 2.5 2.5 1.3456-.0013 2.4488-1.0674 2.4961-2.4121.0025906-.029226.003894-.058551.0039062-.087891v-7.2441l5-1.4277v3.1719l2-1v-3.5c-.000916-.56314-.4664-1.0145-1.0293-.99805zm-1.4707 6.998c-.277 0-.5.223-.5.5v5c0 .277.223.5.5.5s.5-.223.5-.5v-5c0-.277-.223-.5-.5-.5zm2 1c-.277 0-.5.223-.5.5v3c0 .277.223.5.5.5s.5-.223.5-.5v-3c0-.277-.223-.5-.5-.5zm-4 1c-.277 0-.5.223-.5.5v1c0 .277.223.5.5.5s.5-.223.5-.5v-1c0-.277-.223-.5-.5-.5zm6 0c-.277 0-.5.223-.5.5v1c0 .277.223.5.5.5s.5-.223.5-.5v-1c0-.277-.223-.5-.5-.5z" fill="url(#a)"/></svg> \ No newline at end of file
diff --git a/editor/icons/icon_crosshair.svg b/editor/icons/icon_crosshair.svg
new file mode 100644
index 0000000000..b6fa5ec654
--- /dev/null
+++ b/editor/icons/icon_crosshair.svg
@@ -0,0 +1 @@
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m6 1v5h-5v1 3h5v5h4v-5h5v-4h-5v-5z" fill-opacity=".627451"/><path d="m2 7v2l5.0000803.0000197-.0000803 4.9999803h2l-.0000803-4.9999803 5.0000803-.0000197v-2l-5.0000803.0001803.0000803-5.0001803h-2l.0000803 5.0001803z" fill="#fefefe" fill-opacity=".862745"/></svg> \ No newline at end of file
diff --git a/editor/import/editor_scene_importer_gltf.cpp b/editor/import/editor_scene_importer_gltf.cpp
index f5128103f3..a418915830 100644
--- a/editor/import/editor_scene_importer_gltf.cpp
+++ b/editor/import/editor_scene_importer_gltf.cpp
@@ -1302,6 +1302,8 @@ Error EditorSceneImporterGLTF::_parse_images(GLTFState &state, const String &p_b
if (mimetype.findn("png") != -1) {
//is a png
+ ERR_FAIL_COND_V(Image::_png_mem_loader_func == NULL, ERR_UNAVAILABLE);
+
const Ref<Image> img = Image::_png_mem_loader_func(data_ptr, data_size);
ERR_FAIL_COND_V(img.is_null(), ERR_FILE_CORRUPT);
@@ -1316,6 +1318,8 @@ Error EditorSceneImporterGLTF::_parse_images(GLTFState &state, const String &p_b
if (mimetype.findn("jpeg") != -1) {
//is a jpg
+ ERR_FAIL_COND_V(Image::_jpg_mem_loader_func == NULL, ERR_UNAVAILABLE);
+
const Ref<Image> img = Image::_jpg_mem_loader_func(data_ptr, data_size);
ERR_FAIL_COND_V(img.is_null(), ERR_FILE_CORRUPT);
@@ -2329,7 +2333,11 @@ Error EditorSceneImporterGLTF::_parse_animations(GLTFState &state) {
Array samplers = d["samplers"];
if (d.has("name")) {
- animation.name = _sanitize_scene_name(d["name"]);
+ String name = d["name"];
+ if (name.begins_with("loop") || name.ends_with("loop") || name.begins_with("cycle") || name.ends_with("cycle")) {
+ animation.loop = true;
+ }
+ animation.name = _sanitize_scene_name(name);
}
for (int j = 0; j < channels.size(); j++) {
@@ -2735,6 +2743,10 @@ void EditorSceneImporterGLTF::_import_animation(GLTFState &state, AnimationPlaye
animation.instance();
animation->set_name(name);
+ if (anim.loop) {
+ animation->set_loop(true);
+ }
+
float length = 0;
for (Map<int, GLTFAnimation::Track>::Element *E = anim.tracks.front(); E; E = E->next()) {
diff --git a/editor/import/editor_scene_importer_gltf.h b/editor/import/editor_scene_importer_gltf.h
index 4a91b99aa7..78d7106b0d 100644
--- a/editor/import/editor_scene_importer_gltf.h
+++ b/editor/import/editor_scene_importer_gltf.h
@@ -262,6 +262,7 @@ class EditorSceneImporterGLTF : public EditorSceneImporter {
};
struct GLTFAnimation {
+ bool loop = false;
enum Interpolation {
INTERP_LINEAR,
diff --git a/editor/import/resource_importer_obj.cpp b/editor/import/resource_importer_obj.cpp
index 06bbe17785..b1ed59a2db 100644
--- a/editor/import/resource_importer_obj.cpp
+++ b/editor/import/resource_importer_obj.cpp
@@ -203,7 +203,7 @@ static Error _parse_material_library(const String &p_path, Map<String, Ref<Spati
return OK;
}
-static Error _parse_obj(const String &p_path, List<Ref<Mesh> > &r_meshes, bool p_single_mesh, bool p_generate_tangents, bool p_optimize, Vector3 p_scale_mesh, List<String> *r_missing_deps) {
+static Error _parse_obj(const String &p_path, List<Ref<Mesh> > &r_meshes, bool p_single_mesh, bool p_generate_tangents, bool p_optimize, Vector3 p_scale_mesh, Vector3 p_offset_mesh, List<String> *r_missing_deps) {
FileAccessRef f = FileAccess::open(p_path, FileAccess::READ);
ERR_FAIL_COND_V_MSG(!f, ERR_CANT_OPEN, vformat("Couldn't open OBJ file '%s', it may not exist or not be readable.", p_path));
@@ -213,6 +213,7 @@ static Error _parse_obj(const String &p_path, List<Ref<Mesh> > &r_meshes, bool p
bool generate_tangents = p_generate_tangents;
Vector3 scale_mesh = p_scale_mesh;
+ Vector3 offset_mesh = p_offset_mesh;
int mesh_flags = p_optimize ? Mesh::ARRAY_COMPRESS_DEFAULT : 0;
Vector<Vector3> vertices;
@@ -245,9 +246,9 @@ static Error _parse_obj(const String &p_path, List<Ref<Mesh> > &r_meshes, bool p
Vector<String> v = l.split(" ", false);
ERR_FAIL_COND_V(v.size() < 4, ERR_FILE_CORRUPT);
Vector3 vtx;
- vtx.x = v[1].to_float() * scale_mesh.x;
- vtx.y = v[2].to_float() * scale_mesh.y;
- vtx.z = v[3].to_float() * scale_mesh.z;
+ vtx.x = v[1].to_float() * scale_mesh.x + offset_mesh.x;
+ vtx.y = v[2].to_float() * scale_mesh.y + offset_mesh.y;
+ vtx.z = v[3].to_float() * scale_mesh.z + offset_mesh.z;
vertices.push_back(vtx);
} else if (l.begins_with("vt ")) {
//uv
@@ -421,7 +422,7 @@ Node *EditorOBJImporter::import_scene(const String &p_path, uint32_t p_flags, in
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), r_missing_deps);
+ 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);
if (err != OK) {
if (r_err) {
@@ -489,6 +490,7 @@ void ResourceImporterOBJ::get_import_options(List<ImportOption> *r_options, int
r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "generate_tangents"), true));
r_options->push_back(ImportOption(PropertyInfo(Variant::VECTOR3, "scale_mesh"), Vector3(1, 1, 1)));
+ r_options->push_back(ImportOption(PropertyInfo(Variant::VECTOR3, "offset_mesh"), Vector3(0, 0, 0)));
r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "optimize_mesh"), true));
}
bool ResourceImporterOBJ::get_option_visibility(const String &p_option, const Map<StringName, Variant> &p_options) const {
@@ -500,7 +502,7 @@ Error ResourceImporterOBJ::import(const String &p_source_file, const String &p_s
List<Ref<Mesh> > meshes;
- Error err = _parse_obj(p_source_file, meshes, true, p_options["generate_tangents"], p_options["optimize_mesh"], p_options["scale_mesh"], NULL);
+ Error err = _parse_obj(p_source_file, meshes, true, p_options["generate_tangents"], p_options["optimize_mesh"], p_options["scale_mesh"], p_options["offset_mesh"], NULL);
ERR_FAIL_COND_V(err != OK, err);
ERR_FAIL_COND_V(meshes.size() != 1, ERR_BUG);
diff --git a/editor/plugins/animation_player_editor_plugin.cpp b/editor/plugins/animation_player_editor_plugin.cpp
index 5b41da6e8e..5e69ce4e69 100644
--- a/editor/plugins/animation_player_editor_plugin.cpp
+++ b/editor/plugins/animation_player_editor_plugin.cpp
@@ -997,9 +997,9 @@ void AnimationPlayerEditor::_animation_duplicate() {
String new_name = current;
while (player->has_animation(new_name)) {
-
new_name = new_name + " (copy)";
}
+ new_anim->set_name(new_name);
undo_redo->create_action(TTR("Duplicate Animation"));
undo_redo->add_do_method(player, "add_animation", new_name, new_anim);
diff --git a/editor/plugins/animation_tree_editor_plugin.cpp b/editor/plugins/animation_tree_editor_plugin.cpp
index a0b58b8f7e..8dc7e4638d 100644
--- a/editor/plugins/animation_tree_editor_plugin.cpp
+++ b/editor/plugins/animation_tree_editor_plugin.cpp
@@ -39,6 +39,7 @@
#include "core/os/input.h"
#include "core/os/keyboard.h"
#include "core/project_settings.h"
+#include "editor/editor_scale.h"
#include "scene/animation/animation_blend_tree.h"
#include "scene/animation/animation_player.h"
#include "scene/gui/menu_button.h"
@@ -284,7 +285,7 @@ AnimationTreeEditorPlugin::AnimationTreeEditorPlugin(EditorNode *p_node) {
editor = p_node;
anim_tree_editor = memnew(AnimationTreeEditor);
- anim_tree_editor->set_custom_minimum_size(Size2(0, 300));
+ anim_tree_editor->set_custom_minimum_size(Size2(0, 300) * EDSCALE);
button = editor->add_bottom_panel_item(TTR("AnimationTree"), anim_tree_editor);
button->hide();
diff --git a/editor/plugins/asset_library_editor_plugin.cpp b/editor/plugins/asset_library_editor_plugin.cpp
index 5d73ffa209..bdef108ef2 100644
--- a/editor/plugins/asset_library_editor_plugin.cpp
+++ b/editor/plugins/asset_library_editor_plugin.cpp
@@ -726,9 +726,9 @@ void EditorAssetLibrary::_image_update(bool use_cache, bool final, const PoolByt
uint8_t jpg_signature[3] = { 255, 216, 255 };
if (r.ptr()) {
- if (memcmp(&r[0], &png_signature[0], 8) == 0) {
+ if ((memcmp(&r[0], &png_signature[0], 8) == 0) && Image::_png_mem_loader_func) {
image->copy_internals_from(Image::_png_mem_loader_func(r.ptr(), len));
- } else if (memcmp(&r[0], &jpg_signature[0], 3) == 0) {
+ } else if ((memcmp(&r[0], &jpg_signature[0], 3) == 0) && Image::_jpg_mem_loader_func) {
image->copy_internals_from(Image::_jpg_mem_loader_func(r.ptr(), len));
}
}
diff --git a/editor/plugins/audio_stream_editor_plugin.cpp b/editor/plugins/audio_stream_editor_plugin.cpp
index b6e5d48a83..60cb2ff54d 100644
--- a/editor/plugins/audio_stream_editor_plugin.cpp
+++ b/editor/plugins/audio_stream_editor_plugin.cpp
@@ -33,6 +33,7 @@
#include "core/io/resource_loader.h"
#include "core/project_settings.h"
#include "editor/audio_stream_preview.h"
+#include "editor/editor_scale.h"
#include "editor/editor_settings.h"
void AudioStreamEditor::_notification(int p_what) {
@@ -208,7 +209,7 @@ void AudioStreamEditor::_bind_methods() {
AudioStreamEditor::AudioStreamEditor() {
- set_custom_minimum_size(Size2(1, 100));
+ set_custom_minimum_size(Size2(1, 100) * EDSCALE);
_current = 0;
_dragging = false;
diff --git a/editor/plugins/canvas_item_editor_plugin.cpp b/editor/plugins/canvas_item_editor_plugin.cpp
index 71afddba11..437a6722d0 100644
--- a/editor/plugins/canvas_item_editor_plugin.cpp
+++ b/editor/plugins/canvas_item_editor_plugin.cpp
@@ -1492,7 +1492,9 @@ bool CanvasItemEditor::_gui_input_rotate(const Ref<InputEvent> &p_event) {
for (List<CanvasItem *>::Element *E = drag_selection.front(); E; E = E->next()) {
CanvasItem *canvas_item = E->get();
drag_to = transform.affine_inverse().xform(m->get_position());
- canvas_item->_edit_set_rotation(snap_angle(canvas_item->_edit_get_rotation() + (drag_from - drag_rotation_center).angle_to(drag_to - drag_rotation_center), canvas_item->_edit_get_rotation()));
+ //Rotate the opposite way if the canvas item's compounded scale has an uneven number of negative elements
+ bool opposite = (canvas_item->get_global_transform().get_scale().sign().dot(canvas_item->get_transform().get_scale().sign()) == 0);
+ canvas_item->_edit_set_rotation(snap_angle(canvas_item->_edit_get_rotation() + (opposite ? -1 : 1) * (drag_from - drag_rotation_center).angle_to(drag_to - drag_rotation_center), canvas_item->_edit_get_rotation()));
viewport->update();
}
return true;
@@ -3987,29 +3989,21 @@ void CanvasItemEditor::_update_scrollbars() {
updating_scroll = true;
- // Move the zoom buttons
+ // Move the zoom buttons.
Point2 controls_vb_begin = Point2(5, 5);
controls_vb_begin += (show_rulers) ? Point2(RULER_WIDTH, RULER_WIDTH) : Point2();
controls_vb->set_begin(controls_vb_begin);
- // Move and resize the scrollbars
- Size2 size = viewport->get_size();
Size2 hmin = h_scroll->get_minimum_size();
Size2 vmin = v_scroll->get_minimum_size();
- v_scroll->set_begin(Point2(size.width - vmin.width, (show_rulers) ? RULER_WIDTH : 0));
- v_scroll->set_end(Point2(size.width, size.height));
-
- h_scroll->set_begin(Point2((show_rulers) ? RULER_WIDTH : 0, size.height - hmin.height));
- h_scroll->set_end(Point2(size.width - vmin.width, size.height));
-
- // Get the visible frame
+ // Get the visible frame.
Size2 screen_rect = Size2(ProjectSettings::get_singleton()->get("display/window/size/width"), ProjectSettings::get_singleton()->get("display/window/size/height"));
Rect2 local_rect = Rect2(Point2(), viewport->get_size() - Size2(vmin.width, hmin.height));
_queue_update_bone_list();
- // Calculate scrollable area
+ // Calculate scrollable area.
Rect2 canvas_item_rect = Rect2(Point2(), screen_rect);
if (editor->get_edited_scene()) {
Rect2 content_rect = _get_encompassing_rect(editor->get_edited_scene());
@@ -4019,7 +4013,8 @@ void CanvasItemEditor::_update_scrollbars() {
canvas_item_rect.size += screen_rect * 2;
canvas_item_rect.position -= screen_rect;
- // Constraints the view offset and updates the scrollbars
+ // Constraints the view offset and updates the scrollbars.
+ Size2 size = viewport->get_size();
Point2 begin = canvas_item_rect.position;
Point2 end = canvas_item_rect.position + canvas_item_rect.size - local_rect.size / zoom;
bool constrain_editor_view = bool(EditorSettings::get_singleton()->get("editors/2d/constrain_editor_view"));
@@ -4066,7 +4061,13 @@ void CanvasItemEditor::_update_scrollbars() {
h_scroll->set_page(screen_rect.x);
}
- // Calculate scrollable area
+ // Move and resize the scrollbars, avoiding overlap.
+ v_scroll->set_begin(Point2(size.width - vmin.width, (show_rulers) ? RULER_WIDTH : 0));
+ v_scroll->set_end(Point2(size.width, size.height - (h_scroll->is_visible() ? hmin.height : 0)));
+ h_scroll->set_begin(Point2((show_rulers) ? RULER_WIDTH : 0, size.height - hmin.height));
+ h_scroll->set_end(Point2(size.width - (v_scroll->is_visible() ? vmin.width : 0), size.height));
+
+ // Calculate scrollable area.
v_scroll->set_value(view_offset.y);
h_scroll->set_value(view_offset.x);
@@ -4216,11 +4217,15 @@ void CanvasItemEditor::_zoom_on_position(float p_zoom, Point2 p_position) {
void CanvasItemEditor::_update_zoom_label() {
String zoom_text;
+ // The zoom level displayed is relative to the editor scale
+ // (like in most image editors). Its lower bound is clamped to 1 as some people
+ // lower the editor scale to increase the available real estate,
+ // even if their display doesn't have a particularly low DPI.
if (zoom >= 10) {
- // Don't show a decimal when the zoom level is higher than 1000 %
- zoom_text = rtos(Math::round(zoom * 100)) + " %";
+ // Don't show a decimal when the zoom level is higher than 1000 %.
+ zoom_text = rtos(Math::round((zoom / MAX(1, EDSCALE)) * 100)) + " %";
} else {
- zoom_text = rtos(Math::stepify(zoom * 100, 0.1)) + " %";
+ zoom_text = rtos(Math::stepify((zoom / MAX(1, EDSCALE)) * 100, 0.1)) + " %";
}
zoom_reset->set_text(zoom_text);
@@ -4231,7 +4236,7 @@ void CanvasItemEditor::_button_zoom_minus() {
}
void CanvasItemEditor::_button_zoom_reset() {
- _zoom_on_position(1.0, viewport_scrollable->get_size() / 2.0);
+ _zoom_on_position(1.0 * EDSCALE, viewport_scrollable->get_size() / 2.0);
}
void CanvasItemEditor::_button_zoom_plus() {
@@ -4993,7 +4998,8 @@ void CanvasItemEditor::_bind_methods() {
Dictionary CanvasItemEditor::get_state() const {
Dictionary state;
- state["zoom"] = zoom;
+ // Take the editor scale into account.
+ state["zoom"] = zoom / MAX(1, EDSCALE);
state["ofs"] = view_offset;
state["grid_offset"] = grid_offset;
state["grid_step"] = grid_step;
@@ -5030,7 +5036,9 @@ void CanvasItemEditor::set_state(const Dictionary &p_state) {
bool update_scrollbars = false;
Dictionary state = p_state;
if (state.has("zoom")) {
- zoom = p_state["zoom"];
+ // Compensate the editor scale, so that the editor scale can be changed
+ // and the zoom level will still be the same (relative to the editor scale).
+ zoom = float(p_state["zoom"]) * EDSCALE;
_update_zoom_label();
}
@@ -5246,11 +5254,11 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) {
show_rulers = true;
show_guides = true;
show_edit_locks = true;
- zoom = 1;
+ zoom = 1.0 / MAX(1, EDSCALE);
view_offset = Point2(-150 - RULER_WIDTH, -95 - RULER_WIDTH);
previous_update_view_offset = view_offset; // Moves the view a little bit to the left so that (0,0) is visible. The values a relative to a 16/10 screen
grid_offset = Point2();
- grid_step = Point2(10, 10);
+ grid_step = Point2(8, 8); // A power-of-two value works better as a default
primary_grid_steps = 8; // A power-of-two value works better as a default
grid_step_multiplier = 0;
snap_rotation_offset = 0;
diff --git a/editor/plugins/cpu_particles_2d_editor_plugin.cpp b/editor/plugins/cpu_particles_2d_editor_plugin.cpp
index 33ae9363dc..655048c271 100644
--- a/editor/plugins/cpu_particles_2d_editor_plugin.cpp
+++ b/editor/plugins/cpu_particles_2d_editor_plugin.cpp
@@ -296,9 +296,9 @@ CPUParticles2DEditorPlugin::CPUParticles2DEditorPlugin(EditorNode *p_node) {
emission_mask->add_child(emvb);
emission_mask_mode = memnew(OptionButton);
emvb->add_margin_child(TTR("Emission Mask"), emission_mask_mode);
- emission_mask_mode->add_item("Solid Pixels", EMISSION_MODE_SOLID);
- emission_mask_mode->add_item("Border Pixels", EMISSION_MODE_BORDER);
- emission_mask_mode->add_item("Directed Border Pixels", EMISSION_MODE_BORDER_DIRECTED);
+ emission_mask_mode->add_item(TTR("Solid Pixels"), EMISSION_MODE_SOLID);
+ emission_mask_mode->add_item(TTR("Border Pixels"), EMISSION_MODE_BORDER);
+ emission_mask_mode->add_item(TTR("Directed Border Pixels"), EMISSION_MODE_BORDER_DIRECTED);
emission_colors = memnew(CheckBox);
emission_colors->set_text(TTR("Capture from Pixel"));
emvb->add_margin_child(TTR("Emission Colors"), emission_colors);
diff --git a/editor/plugins/item_list_editor_plugin.cpp b/editor/plugins/item_list_editor_plugin.cpp
index 39dc130f42..9f836ed0d3 100644
--- a/editor/plugins/item_list_editor_plugin.cpp
+++ b/editor/plugins/item_list_editor_plugin.cpp
@@ -302,7 +302,7 @@ void ItemListEditor::_delete_pressed() {
void ItemListEditor::_edit_items() {
- dialog->popup_centered(Vector2(300, 400) * EDSCALE);
+ dialog->popup_centered_clamped(Vector2(425, 1200) * EDSCALE, 0.8);
}
void ItemListEditor::edit(Node *p_item_list) {
diff --git a/editor/plugins/particles_2d_editor_plugin.cpp b/editor/plugins/particles_2d_editor_plugin.cpp
index 441739de5f..b036368bc8 100644
--- a/editor/plugins/particles_2d_editor_plugin.cpp
+++ b/editor/plugins/particles_2d_editor_plugin.cpp
@@ -424,9 +424,9 @@ Particles2DEditorPlugin::Particles2DEditorPlugin(EditorNode *p_node) {
emission_mask->add_child(emvb);
emission_mask_mode = memnew(OptionButton);
emvb->add_margin_child(TTR("Emission Mask"), emission_mask_mode);
- emission_mask_mode->add_item("Solid Pixels", EMISSION_MODE_SOLID);
- emission_mask_mode->add_item("Border Pixels", EMISSION_MODE_BORDER);
- emission_mask_mode->add_item("Directed Border Pixels", EMISSION_MODE_BORDER_DIRECTED);
+ emission_mask_mode->add_item(TTR("Solid Pixels"), EMISSION_MODE_SOLID);
+ emission_mask_mode->add_item(TTR("Border Pixels"), EMISSION_MODE_BORDER);
+ emission_mask_mode->add_item(TTR("Directed Border Pixels"), EMISSION_MODE_BORDER_DIRECTED);
emission_colors = memnew(CheckBox);
emission_colors->set_text(TTR("Capture from Pixel"));
emvb->add_margin_child(TTR("Emission Colors"), emission_colors);
diff --git a/editor/plugins/polygon_2d_editor_plugin.cpp b/editor/plugins/polygon_2d_editor_plugin.cpp
index de23193df0..04d595461d 100644
--- a/editor/plugins/polygon_2d_editor_plugin.cpp
+++ b/editor/plugins/polygon_2d_editor_plugin.cpp
@@ -1196,7 +1196,9 @@ void Polygon2DEditor::_uv_draw() {
rect.position -= uv_edit_draw->get_size();
rect.size += uv_edit_draw->get_size() * 2.0;
+
updating_uv_scroll = true;
+
uv_hscroll->set_min(rect.position.x);
uv_hscroll->set_max(rect.position.x + rect.size.x);
if (ABS(rect.position.x - (rect.position.x + rect.size.x)) <= uv_edit_draw->get_size().x) {
@@ -1216,6 +1218,14 @@ void Polygon2DEditor::_uv_draw() {
uv_vscroll->set_page(uv_edit_draw->get_size().y);
uv_vscroll->set_value(uv_draw_ofs.y);
}
+
+ Size2 hmin = uv_hscroll->get_combined_minimum_size();
+ Size2 vmin = uv_vscroll->get_combined_minimum_size();
+
+ // Avoid scrollbar overlapping.
+ uv_hscroll->set_anchor_and_margin(MARGIN_RIGHT, ANCHOR_END, uv_vscroll->is_visible() ? -vmin.width : 0);
+ uv_vscroll->set_anchor_and_margin(MARGIN_BOTTOM, ANCHOR_END, uv_hscroll->is_visible() ? -hmin.height : 0);
+
updating_uv_scroll = false;
}
@@ -1467,7 +1477,6 @@ Polygon2DEditor::Polygon2DEditor(EditorNode *p_editor) :
uv_hscroll->set_step(0.001);
uv_edit_draw->add_child(uv_hscroll);
uv_hscroll->set_anchors_and_margins_preset(PRESET_BOTTOM_WIDE);
- uv_hscroll->set_margin(MARGIN_RIGHT, -uv_vscroll->get_size().x * EDSCALE);
uv_hscroll->connect("value_changed", this, "_uv_scroll_changed");
bone_scroll_main_vb = memnew(VBoxContainer);
diff --git a/editor/plugins/resource_preloader_editor_plugin.cpp b/editor/plugins/resource_preloader_editor_plugin.cpp
index d423be7d24..fb04f50827 100644
--- a/editor/plugins/resource_preloader_editor_plugin.cpp
+++ b/editor/plugins/resource_preloader_editor_plugin.cpp
@@ -32,6 +32,7 @@
#include "core/io/resource_loader.h"
#include "core/project_settings.h"
+#include "editor/editor_scale.h"
#include "editor/editor_settings.h"
void ResourcePreloaderEditor::_gui_input(Ref<InputEvent> p_event) {
@@ -438,7 +439,7 @@ ResourcePreloaderEditorPlugin::ResourcePreloaderEditorPlugin(EditorNode *p_node)
editor = p_node;
preloader_editor = memnew(ResourcePreloaderEditor);
- preloader_editor->set_custom_minimum_size(Size2(0, 250));
+ preloader_editor->set_custom_minimum_size(Size2(0, 250) * EDSCALE);
button = editor->add_bottom_panel_item(TTR("ResourcePreloader"), preloader_editor);
button->hide();
diff --git a/editor/plugins/script_editor_plugin.cpp b/editor/plugins/script_editor_plugin.cpp
index 335466b0c5..f13abd47a9 100644
--- a/editor/plugins/script_editor_plugin.cpp
+++ b/editor/plugins/script_editor_plugin.cpp
@@ -1004,8 +1004,8 @@ void ScriptEditor::_menu_option(int p_option) {
ScriptEditorBase *current = _get_current_editor();
switch (p_option) {
case FILE_NEW: {
- script_create_dialog->config("Node", "new_script");
- script_create_dialog->popup_centered(Size2(300, 300) * EDSCALE);
+ script_create_dialog->config("Node", "new_script", false, false);
+ script_create_dialog->popup_centered();
} break;
case FILE_NEW_TEXTFILE: {
file_dialog->set_mode(EditorFileDialog::MODE_SAVE_FILE);
diff --git a/editor/plugins/script_text_editor.cpp b/editor/plugins/script_text_editor.cpp
index f0e4a4bfdc..1432c3fc63 100644
--- a/editor/plugins/script_text_editor.cpp
+++ b/editor/plugins/script_text_editor.cpp
@@ -691,13 +691,16 @@ void ScriptTextEditor::_update_bookmark_list() {
bookmarks_menu->add_separator();
for (int i = 0; i < bookmark_list.size(); i++) {
- String line = code_editor->get_text_edit()->get_line(bookmark_list[i]).strip_edges();
+ // Strip edges to remove spaces or tabs.
+ // Also replace any tabs by spaces, since we can't print tabs in the menu.
+ String line = code_editor->get_text_edit()->get_line(bookmark_list[i]).replace("\t", " ").strip_edges();
+
// Limit the size of the line if too big.
if (line.length() > 50) {
line = line.substr(0, 50);
}
- bookmarks_menu->add_item(String::num((int)bookmark_list[i] + 1) + " - \"" + line + "\"");
+ bookmarks_menu->add_item(String::num((int)bookmark_list[i] + 1) + " - `" + line + "`");
bookmarks_menu->set_item_metadata(bookmarks_menu->get_item_count() - 1, bookmark_list[i]);
}
}
@@ -841,13 +844,16 @@ void ScriptTextEditor::_update_breakpoint_list() {
breakpoints_menu->add_separator();
for (int i = 0; i < breakpoint_list.size(); i++) {
- String line = code_editor->get_text_edit()->get_line(breakpoint_list[i]).strip_edges();
+ // Strip edges to remove spaces or tabs.
+ // Also replace any tabs by spaces, since we can't print tabs in the menu.
+ String line = code_editor->get_text_edit()->get_line(breakpoint_list[i]).replace("\t", " ").strip_edges();
+
// Limit the size of the line if too big.
if (line.length() > 50) {
line = line.substr(0, 50);
}
- breakpoints_menu->add_item(String::num((int)breakpoint_list[i] + 1) + " - \"" + line + "\"");
+ breakpoints_menu->add_item(String::num((int)breakpoint_list[i] + 1) + " - `" + line + "`");
breakpoints_menu->set_item_metadata(breakpoints_menu->get_item_count() - 1, breakpoint_list[i]);
}
}
diff --git a/editor/plugins/shader_editor_plugin.cpp b/editor/plugins/shader_editor_plugin.cpp
index 7e55415134..c0b5053f9d 100644
--- a/editor/plugins/shader_editor_plugin.cpp
+++ b/editor/plugins/shader_editor_plugin.cpp
@@ -35,6 +35,7 @@
#include "core/os/keyboard.h"
#include "core/os/os.h"
#include "editor/editor_node.h"
+#include "editor/editor_scale.h"
#include "editor/editor_settings.h"
#include "editor/property_editor.h"
#include "servers/visual/shader_types.h"
@@ -756,7 +757,7 @@ ShaderEditorPlugin::ShaderEditorPlugin(EditorNode *p_node) {
editor = p_node;
shader_editor = memnew(ShaderEditor(p_node));
- shader_editor->set_custom_minimum_size(Size2(0, 300));
+ shader_editor->set_custom_minimum_size(Size2(0, 300) * EDSCALE);
button = editor->add_bottom_panel_item(TTR("Shader"), shader_editor);
button->hide();
}
diff --git a/editor/plugins/spatial_editor_plugin.cpp b/editor/plugins/spatial_editor_plugin.cpp
index 252f067eb1..31dce720db 100644
--- a/editor/plugins/spatial_editor_plugin.cpp
+++ b/editor/plugins/spatial_editor_plugin.cpp
@@ -2135,6 +2135,13 @@ void SpatialEditorViewport::_notification(int p_what) {
call_deferred("update_transform_gizmo_view");
}
+ if (p_what == NOTIFICATION_READY) {
+ // The crosshair icon doesn't depend on the editor theme.
+ crosshair->set_texture(get_icon("Crosshair", "EditorIcons"));
+ // Set the anchors and margins after changing the icon to ensure it's centered correctly.
+ crosshair->set_anchors_and_margins_preset(PRESET_CENTER);
+ }
+
if (p_what == NOTIFICATION_PROCESS) {
real_t delta = get_process_delta_time();
@@ -2255,6 +2262,10 @@ void SpatialEditorViewport::_notification(int p_what) {
current_camera = camera;
}
+ // Display the crosshair only while freelooking. Hide it otherwise,
+ // as the crosshair can be distracting.
+ crosshair->set_visible(freelook_active);
+
if (show_info) {
String text;
text += "X: " + rtos(current_camera->get_translation().x).pad_decimals(1) + "\n";
@@ -3546,6 +3557,10 @@ SpatialEditorViewport::SpatialEditorViewport(SpatialEditor *p_spatial_editor, Ed
camera->make_current();
surface->set_focus_mode(FOCUS_ALL);
+ crosshair = memnew(TextureRect);
+ crosshair->set_mouse_filter(MOUSE_FILTER_IGNORE);
+ surface->add_child(crosshair);
+
VBoxContainer *vbox = memnew(VBoxContainer);
surface->add_child(vbox);
vbox->set_position(Point2(10, 10) * EDSCALE);
diff --git a/editor/plugins/spatial_editor_plugin.h b/editor/plugins/spatial_editor_plugin.h
index 356646221e..5cc2b24cbb 100644
--- a/editor/plugins/spatial_editor_plugin.h
+++ b/editor/plugins/spatial_editor_plugin.h
@@ -217,6 +217,7 @@ private:
bool freelook_active;
real_t freelook_speed;
+ TextureRect *crosshair;
Label *info_label;
Label *fps_label;
Label *cinema_label;
diff --git a/editor/plugins/texture_region_editor_plugin.cpp b/editor/plugins/texture_region_editor_plugin.cpp
index 26f2968369..f9b1e3b43a 100644
--- a/editor/plugins/texture_region_editor_plugin.cpp
+++ b/editor/plugins/texture_region_editor_plugin.cpp
@@ -136,13 +136,19 @@ void TextureRegionEditor::_region_draw() {
Ref<Texture> select_handle = get_icon("EditorHandle", "EditorIcons");
- Rect2 scroll_rect;
+ Rect2 scroll_rect(Point2(), base_tex->get_size());
- Vector2 endpoints[4] = {
- mtx.basis_xform(rect.position),
- mtx.basis_xform(rect.position + Vector2(rect.size.x, 0)),
- mtx.basis_xform(rect.position + rect.size),
- mtx.basis_xform(rect.position + Vector2(0, rect.size.y))
+ const Vector2 raw_endpoints[4] = {
+ rect.position,
+ rect.position + Vector2(rect.size.x, 0),
+ rect.position + rect.size,
+ rect.position + Vector2(0, rect.size.y)
+ };
+ const Vector2 endpoints[4] = {
+ mtx.basis_xform(raw_endpoints[0]),
+ mtx.basis_xform(raw_endpoints[1]),
+ mtx.basis_xform(raw_endpoints[2]),
+ mtx.basis_xform(raw_endpoints[3])
};
Color color = get_color("mono_color", "Editor");
for (int i = 0; i < 4; i++) {
@@ -164,33 +170,43 @@ void TextureRegionEditor::_region_draw() {
if (snap_mode != SNAP_AUTOSLICE)
edit_draw->draw_texture(select_handle, (endpoints[i] + ofs - (select_handle->get_size() / 2)).floor() - draw_ofs * draw_zoom);
- scroll_rect.expand_to(endpoints[i]);
+ scroll_rect.expand_to(raw_endpoints[i]);
}
- scroll_rect.position -= edit_draw->get_size();
- scroll_rect.size += edit_draw->get_size() * 2.0;
+ const Size2 scroll_margin = edit_draw->get_size() / draw_zoom;
+ scroll_rect.position -= scroll_margin;
+ scroll_rect.size += scroll_margin * 2;
updating_scroll = true;
+
hscroll->set_min(scroll_rect.position.x);
hscroll->set_max(scroll_rect.position.x + scroll_rect.size.x);
- if (ABS(scroll_rect.position.x - (scroll_rect.position.x + scroll_rect.size.x)) <= edit_draw->get_size().x) {
+ if (ABS(scroll_rect.position.x - (scroll_rect.position.x + scroll_rect.size.x)) <= scroll_margin.x) {
hscroll->hide();
} else {
hscroll->show();
- hscroll->set_page(edit_draw->get_size().x);
+ hscroll->set_page(scroll_margin.x);
hscroll->set_value(draw_ofs.x);
}
vscroll->set_min(scroll_rect.position.y);
vscroll->set_max(scroll_rect.position.y + scroll_rect.size.y);
- if (ABS(scroll_rect.position.y - (scroll_rect.position.y + scroll_rect.size.y)) <= edit_draw->get_size().y) {
+ if (ABS(scroll_rect.position.y - (scroll_rect.position.y + scroll_rect.size.y)) <= scroll_margin.y) {
vscroll->hide();
draw_ofs.y = scroll_rect.position.y;
} else {
vscroll->show();
- vscroll->set_page(edit_draw->get_size().y);
+ vscroll->set_page(scroll_margin.y);
vscroll->set_value(draw_ofs.y);
}
+
+ Size2 hmin = hscroll->get_combined_minimum_size();
+ Size2 vmin = vscroll->get_combined_minimum_size();
+
+ // Avoid scrollbar overlapping.
+ hscroll->set_anchor_and_margin(MARGIN_RIGHT, ANCHOR_END, vscroll->is_visible() ? -vmin.width : 0);
+ vscroll->set_anchor_and_margin(MARGIN_BOTTOM, ANCHOR_END, hscroll->is_visible() ? -hmin.height : 0);
+
updating_scroll = false;
if (node_ninepatch || obj_styleBox.is_valid()) {
@@ -226,15 +242,19 @@ void TextureRegionEditor::_region_input(const Ref<InputEvent> &p_input) {
mtx.elements[2] = -draw_ofs * draw_zoom;
mtx.scale_basis(Vector2(draw_zoom, draw_zoom));
- Vector2 endpoints[8] = {
- mtx.xform(rect.position) + Vector2(-4, -4),
- mtx.xform(rect.position + Vector2(rect.size.x / 2, 0)) + Vector2(0, -4),
- mtx.xform(rect.position + Vector2(rect.size.x, 0)) + Vector2(4, -4),
- mtx.xform(rect.position + Vector2(rect.size.x, rect.size.y / 2)) + Vector2(4, 0),
- mtx.xform(rect.position + rect.size) + Vector2(4, 4),
- mtx.xform(rect.position + Vector2(rect.size.x / 2, rect.size.y)) + Vector2(0, 4),
- mtx.xform(rect.position + Vector2(0, rect.size.y)) + Vector2(-4, 4),
- mtx.xform(rect.position + Vector2(0, rect.size.y / 2)) + Vector2(-4, 0)
+ const real_t handle_radius = 8 * EDSCALE;
+ const real_t handle_offset = 4 * EDSCALE;
+
+ // Position of selection handles.
+ const Vector2 endpoints[8] = {
+ mtx.xform(rect.position) + Vector2(-handle_offset, -handle_offset),
+ mtx.xform(rect.position + Vector2(rect.size.x / 2, 0)) + Vector2(0, -handle_offset),
+ mtx.xform(rect.position + Vector2(rect.size.x, 0)) + Vector2(handle_offset, -handle_offset),
+ mtx.xform(rect.position + Vector2(rect.size.x, rect.size.y / 2)) + Vector2(handle_offset, 0),
+ mtx.xform(rect.position + rect.size) + Vector2(handle_offset, handle_offset),
+ mtx.xform(rect.position + Vector2(rect.size.x / 2, rect.size.y)) + Vector2(0, handle_offset),
+ mtx.xform(rect.position + Vector2(0, rect.size.y)) + Vector2(-handle_offset, handle_offset),
+ mtx.xform(rect.position + Vector2(0, rect.size.y / 2)) + Vector2(-handle_offset, 0)
};
Ref<InputEventMouseButton> mb = p_input;
@@ -347,7 +367,7 @@ void TextureRegionEditor::_region_input(const Ref<InputEvent> &p_input) {
for (int i = 0; i < 8; i++) {
Vector2 tuv = endpoints[i];
- if (tuv.distance_to(Vector2(mb->get_position().x, mb->get_position().y)) < 8) {
+ if (tuv.distance_to(Vector2(mb->get_position().x, mb->get_position().y)) < handle_radius) {
drag_index = i;
}
}
@@ -1008,7 +1028,6 @@ TextureRegionEditor::TextureRegionEditor(EditorNode *p_editor) {
hscroll->set_step(0.001);
edit_draw->add_child(hscroll);
hscroll->set_anchors_and_margins_preset(PRESET_BOTTOM_WIDE);
- hscroll->set_margin(MARGIN_RIGHT, -vscroll->get_size().x * EDSCALE);
hscroll->connect("value_changed", this, "_scroll_changed");
updating_scroll = false;
diff --git a/editor/plugins/tile_set_editor_plugin.cpp b/editor/plugins/tile_set_editor_plugin.cpp
index b64ff6119c..b24d5add9f 100644
--- a/editor/plugins/tile_set_editor_plugin.cpp
+++ b/editor/plugins/tile_set_editor_plugin.cpp
@@ -1303,12 +1303,14 @@ void TileSetEditor::_on_workspace_input(const Ref<InputEvent> &p_ie) {
Size2 tile_workspace_size = edited_region.position + edited_region.size + WORKSPACE_MARGIN * 2;
Size2 workspace_minsize = workspace->get_custom_minimum_size();
- if (tile_workspace_size.x > workspace_minsize.x && tile_workspace_size.y > workspace_minsize.y) {
- undo_redo->add_do_method(workspace, "set_custom_minimum_size", tile_workspace_size);
+ // If the new region is bigger, just directly change the workspace size to avoid checking all other tiles.
+ if (tile_workspace_size.x > workspace_minsize.x || tile_workspace_size.y > workspace_minsize.y) {
+ Size2 max_workspace_size = Size2(MAX(tile_workspace_size.x, workspace_minsize.x), MAX(tile_workspace_size.y, workspace_minsize.y));
+ undo_redo->add_do_method(workspace, "set_custom_minimum_size", max_workspace_size);
undo_redo->add_undo_method(workspace, "set_custom_minimum_size", workspace_minsize);
- undo_redo->add_do_method(workspace_container, "set_custom_minimum_size", tile_workspace_size);
+ undo_redo->add_do_method(workspace_container, "set_custom_minimum_size", max_workspace_size);
undo_redo->add_undo_method(workspace_container, "set_custom_minimum_size", workspace_minsize);
- undo_redo->add_do_method(workspace_overlay, "set_custom_minimum_size", tile_workspace_size);
+ undo_redo->add_do_method(workspace_overlay, "set_custom_minimum_size", max_workspace_size);
undo_redo->add_undo_method(workspace_overlay, "set_custom_minimum_size", workspace_minsize);
} else if (workspace_minsize.x > get_current_texture()->get_size().x + WORKSPACE_MARGIN.x * 2 || workspace_minsize.y > get_current_texture()->get_size().y + WORKSPACE_MARGIN.y * 2) {
undo_redo->add_do_method(this, "update_workspace_minsize");
@@ -1803,8 +1805,6 @@ void TileSetEditor::_on_tool_clicked(int p_tool) {
Ref<ConvexPolygonShape2D> _convex = memnew(ConvexPolygonShape2D);
edited_collision_shape = _convex;
_set_edited_shape_points(_get_collision_shape_points(concave));
- } else {
- // Shouldn't happen
}
for (int i = 0; i < sd.size(); i++) {
if (sd[i].get("shape") == previous_shape) {
@@ -3267,12 +3267,16 @@ void TileSetEditor::update_workspace_minsize() {
List<int> *tiles = new List<int>();
tileset->get_tile_list(tiles);
for (List<int>::Element *E = tiles->front(); E; E = E->next()) {
- if (tileset->tile_get_texture(E->get())->get_rid() == current_texture_rid) {
- Rect2i region = tileset->tile_get_region(E->get());
- if (region.position.x + region.size.x > workspace_min_size.x)
- workspace_min_size.x = region.position.x + region.size.x;
- if (region.position.y + region.size.y > workspace_min_size.y)
- workspace_min_size.y = region.position.y + region.size.y;
+ if (tileset->tile_get_texture(E->get())->get_rid() != current_texture_rid) {
+ continue;
+ }
+
+ Rect2i region = tileset->tile_get_region(E->get());
+ if (region.position.x + region.size.x > workspace_min_size.x) {
+ workspace_min_size.x = region.position.x + region.size.x;
+ }
+ if (region.position.y + region.size.y > workspace_min_size.y) {
+ workspace_min_size.y = region.position.y + region.size.y;
}
}
delete tiles;
diff --git a/editor/plugins/visual_shader_editor_plugin.cpp b/editor/plugins/visual_shader_editor_plugin.cpp
index 972e4f2172..e334d4b093 100644
--- a/editor/plugins/visual_shader_editor_plugin.cpp
+++ b/editor/plugins/visual_shader_editor_plugin.cpp
@@ -2852,7 +2852,7 @@ VisualShaderEditorPlugin::VisualShaderEditorPlugin(EditorNode *p_node) {
editor = p_node;
visual_shader_editor = memnew(VisualShaderEditor);
- visual_shader_editor->set_custom_minimum_size(Size2(0, 300));
+ visual_shader_editor->set_custom_minimum_size(Size2(0, 300) * EDSCALE);
button = editor->add_bottom_panel_item(TTR("VisualShader"), visual_shader_editor);
button->hide();
diff --git a/editor/project_export.cpp b/editor/project_export.cpp
index 73564191e1..8245264e0d 100644
--- a/editor/project_export.cpp
+++ b/editor/project_export.cpp
@@ -1072,6 +1072,8 @@ ProjectExportDialog::ProjectExportDialog() {
main_vb->add_child(hbox);
hbox->set_v_size_flags(SIZE_EXPAND_FILL);
+ // Presets list.
+
VBoxContainer *preset_vb = memnew(VBoxContainer);
preset_vb->set_h_size_flags(Control::SIZE_EXPAND_FILL);
hbox->add_child(preset_vb);
@@ -1099,6 +1101,8 @@ ProjectExportDialog::ProjectExportDialog() {
preset_hb->add_child(delete_preset);
delete_preset->connect("pressed", this, "_delete_preset");
+ // Preset settings.
+
VBoxContainer *settings_vb = memnew(VBoxContainer);
settings_vb->set_h_size_flags(Control::SIZE_EXPAND_FILL);
hbox->add_child(settings_vb);
@@ -1119,18 +1123,24 @@ ProjectExportDialog::ProjectExportDialog() {
export_path->set_save_mode();
export_path->connect("property_changed", this, "_export_path_changed");
+ // Subsections.
+
sections = memnew(TabContainer);
sections->set_tab_align(TabContainer::ALIGN_LEFT);
sections->set_use_hidden_tabs_for_min_size(true);
settings_vb->add_child(sections);
sections->set_v_size_flags(SIZE_EXPAND_FILL);
+ // Main preset parameters.
+
parameters = memnew(EditorInspector);
sections->add_child(parameters);
parameters->set_name(TTR("Options"));
parameters->set_v_size_flags(SIZE_EXPAND_FILL);
parameters->connect("property_edited", this, "_update_parameters");
+ // Resources export parameters.
+
VBoxContainer *resources_vb = memnew(VBoxContainer);
sections->add_child(resources_vb);
resources_vb->set_name(TTR("Resources"));
@@ -1165,10 +1175,17 @@ ProjectExportDialog::ProjectExportDialog() {
exclude_filters);
exclude_filters->connect("text_changed", this, "_filter_changed");
+ // Patch packages.
+
VBoxContainer *patch_vb = memnew(VBoxContainer);
sections->add_child(patch_vb);
patch_vb->set_name(TTR("Patches"));
+ // FIXME: Patching support doesn't seem properly implemented yet, so we hide it.
+ // The rest of the code is still kept for now, in the hope that it will be made
+ // functional and reactivated.
+ patch_vb->hide();
+
patches = memnew(Tree);
patch_vb->add_child(patches);
patches->set_v_size_flags(SIZE_EXPAND_FILL);
@@ -1197,6 +1214,8 @@ ProjectExportDialog::ProjectExportDialog() {
patch_erase->connect("confirmed", this, "_patch_deleted");
add_child(patch_erase);
+ // Feature tags.
+
VBoxContainer *feature_vb = memnew(VBoxContainer);
feature_vb->set_name(TTR("Features"));
custom_features = memnew(LineEdit);
@@ -1210,6 +1229,8 @@ ProjectExportDialog::ProjectExportDialog() {
feature_vb->add_margin_child(TTR("Feature List:"), features_panel, true);
sections->add_child(feature_vb);
+ // Script export parameters.
+
updating_script_key = false;
VBoxContainer *script_vb = memnew(VBoxContainer);
@@ -1231,7 +1252,7 @@ ProjectExportDialog::ProjectExportDialog() {
sections->connect("tab_changed", this, "_tab_changed");
- //disable by default
+ // Disable by default.
name->set_editable(false);
export_path->hide();
runnable->set_disabled(true);
@@ -1241,11 +1262,15 @@ ProjectExportDialog::ProjectExportDialog() {
sections->hide();
parameters->edit(NULL);
+ // Deletion dialog.
+
delete_confirm = memnew(ConfirmationDialog);
add_child(delete_confirm);
delete_confirm->get_ok()->set_text(TTR("Delete"));
delete_confirm->connect("confirmed", this, "_delete_preset_confirm");
+ // Export buttons, dialogs and errors.
+
updating = false;
get_cancel()->set_text(TTR("Close"));
diff --git a/editor/project_manager.cpp b/editor/project_manager.cpp
index 0a904a42df..ca3431d3ec 100644
--- a/editor/project_manager.cpp
+++ b/editor/project_manager.cpp
@@ -1981,6 +1981,7 @@ void ProjectManager::_global_menu_action(const Variant &p_id, const Variant &p_m
int id = (int)p_id;
if (id == ProjectList::GLOBAL_NEW_WINDOW) {
List<String> args;
+ args.push_back("-p");
String exec = OS::get_singleton()->get_executable_path();
OS::ProcessID pid = 0;
diff --git a/editor/script_create_dialog.cpp b/editor/script_create_dialog.cpp
index 4c36e15eb4..35d5fe5f70 100644
--- a/editor/script_create_dialog.cpp
+++ b/editor/script_create_dialog.cpp
@@ -46,7 +46,7 @@ void ScriptCreateDialog::_notification(int p_what) {
case NOTIFICATION_THEME_CHANGED:
case NOTIFICATION_ENTER_TREE: {
for (int i = 0; i < ScriptServer::get_language_count(); i++) {
- String lang = ScriptServer::get_language(i)->get_name();
+ String lang = ScriptServer::get_language(i)->get_type();
Ref<Texture> lang_icon = get_icon(lang, "EditorIcons");
if (lang_icon.is_valid()) {
language_menu->set_item_icon(i, lang_icon);
@@ -99,7 +99,7 @@ bool ScriptCreateDialog::_can_be_built_in() {
return (supports_built_in && built_in_enabled);
}
-void ScriptCreateDialog::config(const String &p_base_name, const String &p_base_path, bool p_built_in_enabled) {
+void ScriptCreateDialog::config(const String &p_base_name, const String &p_base_path, bool p_built_in_enabled, bool p_load_enabled) {
class_name->set_text("");
class_name->deselect();
@@ -117,6 +117,7 @@ void ScriptCreateDialog::config(const String &p_base_name, const String &p_base_
file_path->deselect();
built_in_enabled = p_built_in_enabled;
+ load_enabled = p_load_enabled;
_lang_changed(current_language);
_class_name_changed("");
@@ -623,12 +624,12 @@ void ScriptCreateDialog::_msg_path_valid(bool valid, const String &p_msg) {
void ScriptCreateDialog::_update_dialog() {
+ /* "Add Script Dialog" GUI logic and script checks. */
+
bool script_ok = true;
- /* "Add Script Dialog" gui logic and script checks */
+ // Is script path/name valid (order from top to bottom)?
- // Is Script Valid (order from top to bottom)
- get_ok()->set_disabled(true);
if (!is_built_in && !is_path_valid) {
_msg_script_valid(false, TTR("Invalid path."));
script_ok = false;
@@ -641,12 +642,12 @@ void ScriptCreateDialog::_update_dialog() {
_msg_script_valid(false, TTR("Invalid inherited parent name or path."));
script_ok = false;
}
+
if (script_ok) {
_msg_script_valid(true, TTR("Script is valid."));
- get_ok()->set_disabled(false);
}
- /* Does script have named classes */
+ // Does script have named classes?
if (has_named_classes) {
if (is_new_script_created) {
@@ -663,7 +664,7 @@ void ScriptCreateDialog::_update_dialog() {
class_name->set_text("");
}
- /* Is script Built-in */
+ // Is script Built-in?
if (is_built_in) {
file_path->set_editable(false);
@@ -678,38 +679,50 @@ void ScriptCreateDialog::_update_dialog() {
}
}
- /* Is Script created or loaded from existing file */
+ if (!_can_be_built_in()) {
+ internal->set_pressed(false);
+ }
+ internal->set_disabled(!_can_be_built_in());
+
+ // Is Script created or loaded from existing file?
if (is_built_in) {
get_ok()->set_text(TTR("Create"));
parent_name->set_editable(true);
parent_search_button->set_disabled(false);
parent_browse_button->set_disabled(!can_inherit_from_file);
- internal->set_visible(_can_be_built_in());
- internal_label->set_visible(_can_be_built_in());
_msg_path_valid(true, TTR("Built-in script (into scene file)."));
} else if (is_new_script_created) {
- // New Script Created
+ // New script created.
+
get_ok()->set_text(TTR("Create"));
parent_name->set_editable(true);
parent_search_button->set_disabled(false);
parent_browse_button->set_disabled(!can_inherit_from_file);
- internal->set_visible(_can_be_built_in());
- internal_label->set_visible(_can_be_built_in());
if (is_path_valid) {
_msg_path_valid(true, TTR("Will create a new script file."));
}
- } else {
- // Script Loaded
+ } else if (load_enabled) {
+ // Script loaded.
+
get_ok()->set_text(TTR("Load"));
parent_name->set_editable(false);
parent_search_button->set_disabled(true);
parent_browse_button->set_disabled(true);
- internal->set_disabled(!_can_be_built_in());
if (is_path_valid) {
_msg_path_valid(true, TTR("Will load an existing script file."));
}
+ } else {
+ get_ok()->set_text(TTR("Create"));
+ parent_name->set_editable(true);
+ parent_search_button->set_disabled(false);
+ parent_browse_button->set_disabled(!can_inherit_from_file);
+ _msg_path_valid(false, TTR("Script file already exists."));
+
+ script_ok = false;
}
+
+ get_ok()->set_disabled(!script_ok);
}
void ScriptCreateDialog::_bind_methods() {
@@ -727,7 +740,7 @@ void ScriptCreateDialog::_bind_methods() {
ClassDB::bind_method("_create", &ScriptCreateDialog::_create);
ClassDB::bind_method("_browse_class_in_tree", &ScriptCreateDialog::_browse_class_in_tree);
- ClassDB::bind_method(D_METHOD("config", "inherits", "path", "built_in_enabled"), &ScriptCreateDialog::config, DEFVAL(true));
+ ClassDB::bind_method(D_METHOD("config", "inherits", "path", "built_in_enabled", "load_enabled"), &ScriptCreateDialog::config, DEFVAL(true), DEFVAL(true));
ADD_SIGNAL(MethodInfo("script_created", PropertyInfo(Variant::OBJECT, "script", PROPERTY_HINT_RESOURCE_TYPE, "Script")));
}
@@ -834,8 +847,7 @@ ScriptCreateDialog::ScriptCreateDialog() {
internal = memnew(CheckBox);
internal->set_text(TTR("On"));
internal->connect("pressed", this, "_built_in_pressed");
- internal_label = memnew(Label(TTR("Built-in Script:")));
- gc->add_child(internal_label);
+ gc->add_child(memnew(Label(TTR("Built-in Script:"))));
gc->add_child(internal);
/* Path */
@@ -885,8 +897,9 @@ ScriptCreateDialog::ScriptCreateDialog() {
has_named_classes = false;
supports_built_in = false;
can_inherit_from_file = false;
- built_in_enabled = true;
is_built_in = false;
+ built_in_enabled = true;
+ load_enabled = true;
is_new_script_created = true;
}
diff --git a/editor/script_create_dialog.h b/editor/script_create_dialog.h
index 4d13bc9291..00f642fcf7 100644
--- a/editor/script_create_dialog.h
+++ b/editor/script_create_dialog.h
@@ -58,7 +58,6 @@ class ScriptCreateDialog : public ConfirmationDialog {
Button *path_button;
EditorFileDialog *file_browse;
CheckBox *internal;
- Label *internal_label;
VBoxContainer *path_vb;
AcceptDialog *alert;
CreateDialog *select_class;
@@ -75,6 +74,7 @@ class ScriptCreateDialog : public ConfirmationDialog {
bool is_class_name_valid;
bool is_built_in;
bool built_in_enabled;
+ bool load_enabled;
int current_language;
int default_language;
bool re_check_path;
@@ -127,7 +127,7 @@ protected:
static void _bind_methods();
public:
- void config(const String &p_base_name, const String &p_base_path, bool p_built_in_enabled = true);
+ void config(const String &p_base_name, const String &p_base_path, bool p_built_in_enabled = true, bool p_load_enabled = true);
void set_inheritance_base_type(const String &p_base);
ScriptCreateDialog();
};
diff --git a/editor/translations/af.po b/editor/translations/af.po
index 3ca45d41a0..5dfc860107 100644
--- a/editor/translations/af.po
+++ b/editor/translations/af.po
@@ -1240,10 +1240,23 @@ msgid "Error opening package file, not in ZIP format."
msgstr "Fout met oopmaak, die pakket-lêer is nie in zip format nie."
#: editor/editor_asset_installer.cpp
+#, fuzzy
+msgid "%s (Already Exists)"
+msgstr "AutoLaai '%s' bestaan reeds!"
+
+#: editor/editor_asset_installer.cpp
msgid "Uncompressing Assets"
msgstr "Ontpak Bates"
#: editor/editor_asset_installer.cpp editor/project_manager.cpp
+msgid "The following files failed extraction from package:"
+msgstr ""
+
+#: editor/editor_asset_installer.cpp
+msgid "And %s more files."
+msgstr ""
+
+#: editor/editor_asset_installer.cpp editor/project_manager.cpp
#, fuzzy
msgid "Package installed successfully!"
msgstr "Pakket Suksesvol Geïnstalleer!"
@@ -1253,6 +1266,11 @@ msgstr "Pakket Suksesvol Geïnstalleer!"
msgid "Success!"
msgstr "Sukses!"
+#: editor/editor_asset_installer.cpp
+#, fuzzy
+msgid "Package Contents:"
+msgstr "Pakket Installeerder"
+
#: editor/editor_asset_installer.cpp editor/editor_node.cpp
msgid "Install"
msgstr "Installeer"
@@ -1393,6 +1411,11 @@ msgid "Invalid file, not an audio bus layout."
msgstr "Ongeldige lêer, dis nie 'n oudio-bus uitleg nie."
#: editor/editor_audio_buses.cpp
+#, fuzzy
+msgid "Error saving file: %s"
+msgstr "Fout tydens storing van hulpbron!"
+
+#: editor/editor_audio_buses.cpp
msgid "Add Bus"
msgstr "Voeg Bus By"
@@ -2229,10 +2252,6 @@ msgid "New Window"
msgstr ""
#: editor/editor_node.cpp
-msgid "Project export failed with error code %d."
-msgstr ""
-
-#: editor/editor_node.cpp
msgid "Imported resources can't be saved."
msgstr ""
@@ -3084,10 +3103,6 @@ msgstr ""
msgid "Template Package"
msgstr ""
-#: editor/editor_node.cpp editor/project_export.cpp
-msgid "Export Project"
-msgstr ""
-
#: editor/editor_node.cpp
msgid "Export Library"
msgstr ""
@@ -3097,10 +3112,6 @@ msgid "Merge With Existing"
msgstr ""
#: editor/editor_node.cpp
-msgid "Password:"
-msgstr ""
-
-#: editor/editor_node.cpp
msgid "Open & Run a Script"
msgstr ""
@@ -5781,6 +5792,22 @@ 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
+#, fuzzy
+msgid "Directed Border Pixels"
+msgstr "Gidse & Lêers:"
+
+#: editor/plugins/cpu_particles_2d_editor_plugin.cpp
+#: editor/plugins/particles_2d_editor_plugin.cpp
msgid "Capture from Pixel"
msgstr ""
@@ -9533,6 +9560,10 @@ msgid "Export PCK/Zip"
msgstr ""
#: editor/project_export.cpp
+msgid "Export Project"
+msgstr ""
+
+#: editor/project_export.cpp
msgid "Export mode?"
msgstr ""
@@ -9626,10 +9657,6 @@ msgid "Couldn't create project.godot in project path."
msgstr ""
#: editor/project_manager.cpp
-msgid "The following files failed extraction from package:"
-msgstr ""
-
-#: editor/project_manager.cpp
msgid "Rename Project"
msgstr ""
@@ -10821,6 +10848,11 @@ msgstr "Laai 'n bestaande Bus Uitleg."
#: editor/script_create_dialog.cpp
#, fuzzy
+msgid "Script file already exists."
+msgstr "AutoLaai '%s' bestaan reeds!"
+
+#: editor/script_create_dialog.cpp
+#, fuzzy
msgid "Class Name:"
msgstr "Klas:"
@@ -12396,7 +12428,14 @@ msgid "This node has been deprecated. Use AnimationTree instead."
msgstr ""
#: scene/gui/color_picker.cpp
-msgid "Pick a color from the screen."
+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
@@ -12566,10 +12605,6 @@ msgstr ""
#~ msgstr "Kol:"
#, fuzzy
-#~ msgid "Split already exists."
-#~ msgstr "AutoLaai '%s' bestaan reeds!"
-
-#, fuzzy
#~ msgid "Remove Split"
#~ msgstr "Verwyder Seleksie"
diff --git a/editor/translations/ar.po b/editor/translations/ar.po
index 7e71aa7f52..f488274efc 100644
--- a/editor/translations/ar.po
+++ b/editor/translations/ar.po
@@ -1210,10 +1210,24 @@ msgid "Error opening package file, not in ZIP format."
msgstr "حدث خطأ عندÙتح مل٠الحزمة بسبب أن المل٠ليس ÙÙŠ صيغة \"ZIP\"."
#: editor/editor_asset_installer.cpp
+#, fuzzy
+msgid "%s (Already Exists)"
+msgstr "التحميل التلقائي '%s' موجود اصلا!"
+
+#: editor/editor_asset_installer.cpp
msgid "Uncompressing Assets"
msgstr "ÙŠÙكك الضغط عن الأصول"
#: editor/editor_asset_installer.cpp editor/project_manager.cpp
+msgid "The following files failed extraction from package:"
+msgstr ""
+
+#: editor/editor_asset_installer.cpp
+#, fuzzy
+msgid "And %s more files."
+msgstr "%d مزيد من الملÙات"
+
+#: editor/editor_asset_installer.cpp editor/project_manager.cpp
msgid "Package installed successfully!"
msgstr "تم تتبيث الحزمة بنجاح!"
@@ -1222,6 +1236,11 @@ msgstr "تم تتبيث الحزمة بنجاح!"
msgid "Success!"
msgstr "تم بشكل ناجح!"
+#: editor/editor_asset_installer.cpp
+#, fuzzy
+msgid "Package Contents:"
+msgstr "المحتويات:"
+
#: editor/editor_asset_installer.cpp editor/editor_node.cpp
msgid "Install"
msgstr "تثبيت"
@@ -1360,6 +1379,11 @@ msgid "Invalid file, not an audio bus layout."
msgstr "مل٠خطأ، ليس مل٠نسق بيوس الصوت."
#: editor/editor_audio_buses.cpp
+#, fuzzy
+msgid "Error saving file: %s"
+msgstr "خطأ ÙÙŠ Ø­Ùظ مجموعة البلاط!"
+
+#: editor/editor_audio_buses.cpp
msgid "Add Bus"
msgstr "أض٠بيوس"
@@ -2196,10 +2220,6 @@ msgid "New Window"
msgstr ""
#: editor/editor_node.cpp
-msgid "Project export failed with error code %d."
-msgstr "تصدير المشروع Ùشل, رمز الخطأ %d."
-
-#: editor/editor_node.cpp
msgid "Imported resources can't be saved."
msgstr ""
@@ -3123,10 +3143,6 @@ msgstr "إستيراد القوالب من مل٠مضغوط بصيغة Zip"
msgid "Template Package"
msgstr "‌تصدير مدير القوالب"
-#: editor/editor_node.cpp editor/project_export.cpp
-msgid "Export Project"
-msgstr "تصدير المشروع"
-
#: editor/editor_node.cpp
msgid "Export Library"
msgstr "تصدير المكتبة"
@@ -3136,10 +3152,6 @@ msgid "Merge With Existing"
msgstr "دمج مع الموجود"
#: editor/editor_node.cpp
-msgid "Password:"
-msgstr "كلمة السر:"
-
-#: editor/editor_node.cpp
msgid "Open & Run a Script"
msgstr "Ùتح Ùˆ تشغيل كود"
@@ -5904,6 +5916,22 @@ 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
+#, fuzzy
+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 "التقط من البيكسل"
@@ -9745,6 +9773,10 @@ msgid "Export PCK/Zip"
msgstr ""
#: editor/project_export.cpp
+msgid "Export Project"
+msgstr "تصدير المشروع"
+
+#: editor/project_export.cpp
#, fuzzy
msgid "Export mode?"
msgstr "تصدير المشروع"
@@ -9839,10 +9871,6 @@ msgid "Couldn't create project.godot in project path."
msgstr ""
#: editor/project_manager.cpp
-msgid "The following files failed extraction from package:"
-msgstr ""
-
-#: editor/project_manager.cpp
msgid "Rename Project"
msgstr ""
@@ -11054,6 +11082,11 @@ msgstr "تحميل نسق بيوس موجود مسبقاً."
#: editor/script_create_dialog.cpp
#, fuzzy
+msgid "Script file already exists."
+msgstr "التحميل التلقائي '%s' موجود اصلا!"
+
+#: editor/script_create_dialog.cpp
+#, fuzzy
msgid "Class Name:"
msgstr "إسم صنÙ"
@@ -12657,7 +12690,14 @@ msgid "This node has been deprecated. Use AnimationTree instead."
msgstr ""
#: scene/gui/color_picker.cpp
-msgid "Pick a color from the screen."
+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
@@ -12762,6 +12802,12 @@ msgstr "يمكن تعيين المتغيرات Ùقط ÙÙŠ الذروة ."
msgid "Constants cannot be modified."
msgstr ""
+#~ msgid "Project export failed with error code %d."
+#~ msgstr "تصدير المشروع Ùشل, رمز الخطأ %d."
+
+#~ msgid "Password:"
+#~ msgstr "كلمة السر:"
+
#~ msgid "Pause the scene"
#~ msgstr "إيقا٠المشهد مؤقتاً"
@@ -12963,10 +13009,6 @@ msgstr ""
#~ msgstr "العمود:"
#, fuzzy
-#~ msgid "Split already exists."
-#~ msgstr "التحميل التلقائي '%s' موجود اصلا!"
-
-#, fuzzy
#~ msgid "Add Split"
#~ msgstr "إضاÙØ© نقطة"
diff --git a/editor/translations/bg.po b/editor/translations/bg.po
index a4045e0664..8b3fe3d00d 100644
--- a/editor/translations/bg.po
+++ b/editor/translations/bg.po
@@ -1211,10 +1211,24 @@ msgid "Error opening package file, not in ZIP format."
msgstr ""
#: editor/editor_asset_installer.cpp
+#, fuzzy
+msgid "%s (Already Exists)"
+msgstr "Група Ñ Ñ‚Ð¾Ð²Ð° име вече ÑъщеÑтвува."
+
+#: editor/editor_asset_installer.cpp
msgid "Uncompressing Assets"
msgstr "Разархивиране на активи"
#: editor/editor_asset_installer.cpp editor/project_manager.cpp
+msgid "The following files failed extraction from package:"
+msgstr ""
+
+#: editor/editor_asset_installer.cpp
+#, fuzzy
+msgid "And %s more files."
+msgstr "ÐеуÑпешно Ñъздаване на папка."
+
+#: editor/editor_asset_installer.cpp editor/project_manager.cpp
msgid "Package installed successfully!"
msgstr ""
@@ -1223,6 +1237,11 @@ msgstr ""
msgid "Success!"
msgstr "Готово!"
+#: editor/editor_asset_installer.cpp
+#, fuzzy
+msgid "Package Contents:"
+msgstr "Съдържание:"
+
#: editor/editor_asset_installer.cpp editor/editor_node.cpp
msgid "Install"
msgstr "ИнÑталиране"
@@ -1361,6 +1380,11 @@ msgid "Invalid file, not an audio bus layout."
msgstr ""
#: editor/editor_audio_buses.cpp
+#, fuzzy
+msgid "Error saving file: %s"
+msgstr "Грешка при запиÑването на файла!"
+
+#: editor/editor_audio_buses.cpp
msgid "Add Bus"
msgstr ""
@@ -2186,10 +2210,6 @@ msgid "New Window"
msgstr ""
#: editor/editor_node.cpp
-msgid "Project export failed with error code %d."
-msgstr ""
-
-#: editor/editor_node.cpp
msgid "Imported resources can't be saved."
msgstr ""
@@ -3058,10 +3078,6 @@ msgstr "ВнаÑÑне на шаблони от архив във формат Z
msgid "Template Package"
msgstr "Шаблони"
-#: editor/editor_node.cpp editor/project_export.cpp
-msgid "Export Project"
-msgstr "ИзнаÑÑне на проекта"
-
#: editor/editor_node.cpp
msgid "Export Library"
msgstr "ИзнаÑÑне на библиотеката"
@@ -3071,10 +3087,6 @@ msgid "Merge With Existing"
msgstr ""
#: editor/editor_node.cpp
-msgid "Password:"
-msgstr "Парола:"
-
-#: editor/editor_node.cpp
msgid "Open & Run a Script"
msgstr ""
@@ -5821,6 +5833,22 @@ 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
+#, fuzzy
+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 ""
@@ -9624,6 +9652,10 @@ msgid "Export PCK/Zip"
msgstr "ИзнаÑÑне"
#: editor/project_export.cpp
+msgid "Export Project"
+msgstr "ИзнаÑÑне на проекта"
+
+#: editor/project_export.cpp
#, fuzzy
msgid "Export mode?"
msgstr "Режим на изнаÑÑне:"
@@ -9721,10 +9753,6 @@ msgid "Couldn't create project.godot in project path."
msgstr ""
#: editor/project_manager.cpp
-msgid "The following files failed extraction from package:"
-msgstr ""
-
-#: editor/project_manager.cpp
#, fuzzy
msgid "Rename Project"
msgstr "Ðов проект"
@@ -10941,6 +10969,11 @@ msgstr ""
#: editor/script_create_dialog.cpp
#, fuzzy
+msgid "Script file already exists."
+msgstr "Група Ñ Ñ‚Ð¾Ð²Ð° име вече ÑъщеÑтвува."
+
+#: editor/script_create_dialog.cpp
+#, fuzzy
msgid "Class Name:"
msgstr "КлаÑ:"
@@ -12577,7 +12610,14 @@ msgid "This node has been deprecated. Use AnimationTree instead."
msgstr ""
#: scene/gui/color_picker.cpp
-msgid "Pick a color from the screen."
+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
@@ -12681,6 +12721,9 @@ msgstr ""
msgid "Constants cannot be modified."
msgstr ""
+#~ msgid "Password:"
+#~ msgstr "Парола:"
+
#~ msgid "Pause the scene"
#~ msgstr "ПреуÑтановÑване на Ñцената"
diff --git a/editor/translations/bn.po b/editor/translations/bn.po
index aa249eabc6..86ffa156e6 100644
--- a/editor/translations/bn.po
+++ b/editor/translations/bn.po
@@ -1267,10 +1267,24 @@ msgid "Error opening package file, not in ZIP format."
msgstr "জিপ ফরমà§à¦¯à¦¾à¦Ÿ খà§à¦à¦œà§‡ পেতে বà§à¦¯à¦¾à¦°à§à¦¥, পà§à¦¯à¦¾à¦•à§‡à¦œ ফাইল ওপেন করা যায়নি।"
#: editor/editor_asset_installer.cpp
+#, fuzzy
+msgid "%s (Already Exists)"
+msgstr "সà§à¦¥à¦¾à§Ÿà§€à§Ÿà¦¤à¦¾ টগল করà§à¦¨"
+
+#: editor/editor_asset_installer.cpp
msgid "Uncompressing Assets"
msgstr "আনকমà§à¦ªà§à¦°à§‡à¦¸à§à¦¡ অà§à¦¯à¦¾à¦¸à§‡à¦Ÿà¦¸"
#: editor/editor_asset_installer.cpp editor/project_manager.cpp
+msgid "The following files failed extraction from package:"
+msgstr "পà§à¦¯à¦¾à¦•à§‡à¦œ হতে নীমà§à¦¨à§‹à¦•à§à¦¤ ফাইলসমূহ à¦à¦•à§à¦¸à¦Ÿà§à¦°à¦¾à¦•à§à¦Ÿ করা অসফল হয়েছে:"
+
+#: editor/editor_asset_installer.cpp
+#, fuzzy
+msgid "And %s more files."
+msgstr "%d টি অধিক ফাইল(সমূহ)"
+
+#: editor/editor_asset_installer.cpp editor/project_manager.cpp
#, fuzzy
msgid "Package installed successfully!"
msgstr "পà§à¦¯à¦¾à¦•à§‡à¦œ ইনà§à¦¸à¦Ÿà¦² সমà§à¦ªà¦¨à§à¦¨ হয়েছে!"
@@ -1280,6 +1294,11 @@ msgstr "পà§à¦¯à¦¾à¦•à§‡à¦œ ইনà§à¦¸à¦Ÿà¦² সমà§à¦ªà¦¨à§à¦¨ হয়ে
msgid "Success!"
msgstr "সমà§à¦ªà¦¨à§à¦¨ হয়েছে!"
+#: editor/editor_asset_installer.cpp
+#, fuzzy
+msgid "Package Contents:"
+msgstr "ধà§à¦°à§à¦¬à¦•à¦¸à¦®à§‚হ:"
+
#: editor/editor_asset_installer.cpp editor/editor_node.cpp
msgid "Install"
msgstr "ইনà§à¦¸à¦Ÿà¦²"
@@ -1421,6 +1440,11 @@ msgid "Invalid file, not an audio bus layout."
msgstr "ফাইল অডিও বাস লেআউট হিসেবে বà§à¦¯à¦¾à¦¬à¦¹à¦¾à¦°à¦¯à§‹à¦—à§à¦¯ নয়।"
#: editor/editor_audio_buses.cpp
+#, fuzzy
+msgid "Error saving file: %s"
+msgstr "TileSet সংরকà§à¦·à¦£à§‡ সমসà§à¦¯à¦¾ হয়েছে!"
+
+#: editor/editor_audio_buses.cpp
msgid "Add Bus"
msgstr "বাস যোগ করà§à¦¨"
@@ -2292,10 +2316,6 @@ msgid "New Window"
msgstr "উইনà§à¦¡à§‹"
#: editor/editor_node.cpp
-msgid "Project export failed with error code %d."
-msgstr ""
-
-#: editor/editor_node.cpp
msgid "Imported resources can't be saved."
msgstr ""
@@ -3245,10 +3265,6 @@ msgstr "ZIP ফাইল হতে টেমপà§à¦²à§‡à¦Ÿ-সমূহ ইমà
msgid "Template Package"
msgstr "à¦à¦•à§à¦¸à¦ªà§‹à¦°à§à¦Ÿ টেমপà§à¦²à§‡à¦Ÿà¦¸à¦®à§‚হ লোড হচà§à¦›à§‡"
-#: editor/editor_node.cpp editor/project_export.cpp
-msgid "Export Project"
-msgstr "পà§à¦°à¦•à¦²à§à¦ª à¦à¦•à§à¦¸à¦ªà§‹à¦°à§à¦Ÿ করà§à¦¨"
-
#: editor/editor_node.cpp
msgid "Export Library"
msgstr "লাইবà§à¦°à§‡à¦°à¦¿ à¦à¦•à§à¦¸à¦ªà§‹à¦°à§à¦Ÿ করà§à¦¨"
@@ -3258,10 +3274,6 @@ msgid "Merge With Existing"
msgstr "বিদà§à¦¯à¦®à¦¾à¦¨à§‡à¦° সাথে à¦à¦•à¦¤à§à¦°à¦¿à¦¤ করà§à¦¨"
#: editor/editor_node.cpp
-msgid "Password:"
-msgstr "পাসওয়ারà§à¦¡:"
-
-#: editor/editor_node.cpp
msgid "Open & Run a Script"
msgstr "à¦à¦•à¦Ÿà¦¿ সà§à¦•à§à¦°à¦¿à¦ªà§à¦Ÿ খà§à¦²à§à¦¨ à¦à¦¬à¦‚ চালান"
@@ -6139,6 +6151,23 @@ msgstr "Emission Mask সà§à¦¥à¦¾à¦ªà¦¨ করà§à¦¨"
#: editor/plugins/cpu_particles_2d_editor_plugin.cpp
#: editor/plugins/particles_2d_editor_plugin.cpp
#, fuzzy
+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
+#, fuzzy
+msgid "Directed Border Pixels"
+msgstr "পথ à¦à¦¬à¦‚ ফাইল:"
+
+#: editor/plugins/cpu_particles_2d_editor_plugin.cpp
+#: editor/plugins/particles_2d_editor_plugin.cpp
+#, fuzzy
msgid "Capture from Pixel"
msgstr "দৃশà§à¦¯ হতে তৈরি করবেন"
@@ -10111,6 +10140,10 @@ msgid "Export PCK/Zip"
msgstr "à¦à¦•à§à¦¸à¦ªà§‹à¦°à§à¦Ÿ PCK/Zip"
#: editor/project_export.cpp
+msgid "Export Project"
+msgstr "পà§à¦°à¦•à¦²à§à¦ª à¦à¦•à§à¦¸à¦ªà§‹à¦°à§à¦Ÿ করà§à¦¨"
+
+#: editor/project_export.cpp
#, fuzzy
msgid "Export mode?"
msgstr "à¦à¦•à§à¦¸à¦ªà§‹à¦°à§à¦Ÿ মোড:"
@@ -10215,10 +10248,6 @@ msgid "Couldn't create project.godot in project path."
msgstr "পà§à¦°à¦•à¦²à§à¦ªà§‡à¦° পথে engine.cfg তৈরি করা সমà§à¦­à¦¬ হয়নি।"
#: editor/project_manager.cpp
-msgid "The following files failed extraction from package:"
-msgstr "পà§à¦¯à¦¾à¦•à§‡à¦œ হতে নীমà§à¦¨à§‹à¦•à§à¦¤ ফাইলসমূহ à¦à¦•à§à¦¸à¦Ÿà§à¦°à¦¾à¦•à§à¦Ÿ করা অসফল হয়েছে:"
-
-#: editor/project_manager.cpp
#, fuzzy
msgid "Rename Project"
msgstr "নামহীন পà§à¦°à¦•à¦²à§à¦ª"
@@ -11511,6 +11540,11 @@ msgstr "বিদà§à¦¯à¦®à¦¾à¦¨ সà§à¦•à§à¦°à¦¿à¦ªà§à¦Ÿ লোড করà§
#: editor/script_create_dialog.cpp
#, fuzzy
+msgid "Script file already exists."
+msgstr "'%s' অà§à¦¯à¦¾à¦•à¦¶à¦¨ ইতিমধà§à¦¯à§‡à¦‡ বিদà§à¦¯à¦®à¦¾à¦¨!"
+
+#: editor/script_create_dialog.cpp
+#, fuzzy
msgid "Class Name:"
msgstr "কà§à¦²à¦¾à¦¸ নাম:"
@@ -13226,7 +13260,14 @@ msgid "This node has been deprecated. Use AnimationTree instead."
msgstr ""
#: scene/gui/color_picker.cpp
-msgid "Pick a color from the screen."
+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
@@ -13341,6 +13382,9 @@ msgstr ""
msgid "Constants cannot be modified."
msgstr ""
+#~ msgid "Password:"
+#~ msgstr "পাসওয়ারà§à¦¡:"
+
#~ msgid "Pause the scene"
#~ msgstr "দৃশà§à¦¯à¦Ÿà¦¿à¦•à§‡ বিরতি দিন"
@@ -13632,10 +13676,6 @@ msgstr ""
#~ msgstr "ফোলà§à¦¡à¦¾à¦° তৈরি করà§à¦¨"
#, fuzzy
-#~ msgid "Already existing"
-#~ msgstr "সà§à¦¥à¦¾à§Ÿà§€à§Ÿà¦¤à¦¾ টগল করà§à¦¨"
-
-#, fuzzy
#~ msgid "Custom Node"
#~ msgstr "নোড-সমূহ করà§à¦¤à¦¨/কাট করà§à¦¨"
@@ -13687,10 +13727,6 @@ msgstr ""
#~ msgstr "PathFollow2D à¦à¦•à¦®à¦¾à¦¤à§à¦° Path2D à¦à¦° অংশ হিসেবে নিরà§à¦§à¦¾à¦°à¦¨ করালেই কাজ করে।"
#, fuzzy
-#~ msgid "Split already exists."
-#~ msgstr "'%s' অà§à¦¯à¦¾à¦•à¦¶à¦¨ ইতিমধà§à¦¯à§‡à¦‡ বিদà§à¦¯à¦®à¦¾à¦¨!"
-
-#, fuzzy
#~ msgid "Add Split"
#~ msgstr "ইনপà§à¦Ÿ যোগ করà§à¦¨"
diff --git a/editor/translations/ca.po b/editor/translations/ca.po
index 2a76448e94..441fa30e91 100644
--- a/editor/translations/ca.po
+++ b/editor/translations/ca.po
@@ -8,12 +8,13 @@
# Rubén Moreno <ruben.moreno.romero@gmail.com>, 2018.
# roger <616steam@gmail.com>, 2019.
# Roger BR <drai_kin@hotmail.com>, 2019.
+# Adolfo Jayme Barrientos <fitojb@ubuntu.com>, 2020.
msgid ""
msgstr ""
"Project-Id-Version: Godot Engine editor\n"
"POT-Creation-Date: \n"
-"PO-Revision-Date: 2019-12-21 08:37+0000\n"
-"Last-Translator: roger <616steam@gmail.com>\n"
+"PO-Revision-Date: 2020-01-03 21:21+0000\n"
+"Last-Translator: Adolfo Jayme Barrientos <fitojb@ubuntu.com>\n"
"Language-Team: Catalan <https://hosted.weblate.org/projects/godot-engine/"
"godot/ca/>\n"
"Language: ca\n"
@@ -654,9 +655,8 @@ msgid "Copy"
msgstr "Copia"
#: editor/animation_track_editor.cpp
-#, fuzzy
msgid "Select All/None"
-msgstr "Seleccionar Totes/Cap"
+msgstr "(Des)selecciona-ho tot"
#: editor/animation_track_editor_plugins.cpp
msgid "Add Audio Track Clip"
@@ -1201,10 +1201,24 @@ msgid "Error opening package file, not in ZIP format."
msgstr "Error en obrir el arxiu comprimit, el fitxer no té el format ZIP."
#: editor/editor_asset_installer.cpp
+#, fuzzy
+msgid "%s (Already Exists)"
+msgstr "Ja existeix"
+
+#: editor/editor_asset_installer.cpp
msgid "Uncompressing Assets"
msgstr "Descomprimint Recursos"
#: editor/editor_asset_installer.cpp editor/project_manager.cpp
+msgid "The following files failed extraction from package:"
+msgstr "Ha fracassat l'extracció del paquet dels següents fitxers:"
+
+#: editor/editor_asset_installer.cpp
+#, fuzzy
+msgid "And %s more files."
+msgstr "%d fitxer(s) més"
+
+#: editor/editor_asset_installer.cpp editor/project_manager.cpp
msgid "Package installed successfully!"
msgstr "Paquet instal·lat amb èxit!"
@@ -1213,6 +1227,11 @@ msgstr "Paquet instal·lat amb èxit!"
msgid "Success!"
msgstr "Èxit!"
+#: editor/editor_asset_installer.cpp
+#, fuzzy
+msgid "Package Contents:"
+msgstr "Continguts:"
+
#: editor/editor_asset_installer.cpp editor/editor_node.cpp
msgid "Install"
msgstr "Instal·la"
@@ -1352,6 +1371,11 @@ msgid "Invalid file, not an audio bus layout."
msgstr "Fitxer incorrecte. No és un disseny de bus d'àudio."
#: editor/editor_audio_buses.cpp
+#, fuzzy
+msgid "Error saving file: %s"
+msgstr "Error en desar el fitxer!"
+
+#: editor/editor_audio_buses.cpp
msgid "Add Bus"
msgstr "Afegeix Bus"
@@ -2166,10 +2190,6 @@ msgid "New Window"
msgstr "Nova finestra"
#: editor/editor_node.cpp
-msgid "Project export failed with error code %d."
-msgstr "L'exportació del projecte ha fallat amb el codi d'error %d."
-
-#: editor/editor_node.cpp
msgid "Imported resources can't be saved."
msgstr "Els recursos importats no es poden guardar."
@@ -3102,10 +3122,6 @@ msgstr "Importa Plantilles des d'un Fitxer ZIP"
msgid "Template Package"
msgstr "Gestor de Plantilles d'Exportació"
-#: editor/editor_node.cpp editor/project_export.cpp
-msgid "Export Project"
-msgstr "Exporta Projecte"
-
#: editor/editor_node.cpp
msgid "Export Library"
msgstr "Exporta Biblioteca"
@@ -3115,10 +3131,6 @@ msgid "Merge With Existing"
msgstr "Combina amb Existents"
#: editor/editor_node.cpp
-msgid "Password:"
-msgstr "Contrasenya:"
-
-#: editor/editor_node.cpp
msgid "Open & Run a Script"
msgstr "Obre i Executa un Script"
@@ -5089,17 +5101,15 @@ msgstr "Tot"
#: editor/plugins/asset_library_editor_plugin.cpp
msgid "No results for \"%s\"."
-msgstr "Cap resultat per \"%s\"."
+msgstr "No hi ha cap resultat per a «%s»."
#: editor/plugins/asset_library_editor_plugin.cpp
-#, fuzzy
msgid "Import..."
-msgstr "ReImporta..."
+msgstr "Importa…"
#: editor/plugins/asset_library_editor_plugin.cpp
-#, fuzzy
msgid "Plugins..."
-msgstr "Connectors"
+msgstr "Connectors…"
#: editor/plugins/asset_library_editor_plugin.cpp editor/project_manager.cpp
msgid "Sort:"
@@ -5115,9 +5125,8 @@ msgid "Site:"
msgstr "Lloc:"
#: editor/plugins/asset_library_editor_plugin.cpp
-#, fuzzy
msgid "Support"
-msgstr "Suport..."
+msgstr "Assistència"
#: editor/plugins/asset_library_editor_plugin.cpp
msgid "Official"
@@ -5128,9 +5137,8 @@ msgid "Testing"
msgstr "Provant"
#: editor/plugins/asset_library_editor_plugin.cpp
-#, fuzzy
msgid "Loading..."
-msgstr "Carregar..."
+msgstr "S’està carregant…"
#: editor/plugins/asset_library_editor_plugin.cpp
msgid "Assets ZIP File"
@@ -5819,6 +5827,22 @@ msgstr "Màscara d'Emissió"
#: 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
+#, fuzzy
+msgid "Directed Border Pixels"
+msgstr "Directoris i Fitxers:"
+
+#: editor/plugins/cpu_particles_2d_editor_plugin.cpp
+#: editor/plugins/particles_2d_editor_plugin.cpp
msgid "Capture from Pixel"
msgstr "Captura des d'un Píxel"
@@ -9703,6 +9727,10 @@ msgid "Export PCK/Zip"
msgstr "Exporta PCK/Zip"
#: editor/project_export.cpp
+msgid "Export Project"
+msgstr "Exporta Projecte"
+
+#: editor/project_export.cpp
msgid "Export mode?"
msgstr "Mode d'Exportació?"
@@ -9796,10 +9824,6 @@ msgid "Couldn't create project.godot in project path."
msgstr "No es pot crear el fitxer 'project.godot' en el camí del projecte."
#: editor/project_manager.cpp
-msgid "The following files failed extraction from package:"
-msgstr "Ha fracassat l'extracció del paquet dels següents fitxers:"
-
-#: editor/project_manager.cpp
msgid "Rename Project"
msgstr "Reanomena el Projecte"
@@ -11075,6 +11099,11 @@ msgstr "Es carregarà un fitxer de script existent."
#: editor/script_create_dialog.cpp
#, fuzzy
+msgid "Script file already exists."
+msgstr "L'Acció '%s' ja existeix!"
+
+#: editor/script_create_dialog.cpp
+#, fuzzy
msgid "Class Name:"
msgstr "Nom de Classe"
@@ -12233,7 +12262,7 @@ msgstr ""
#: platform/javascript/export/export.cpp
msgid "Stop HTTP Server"
-msgstr "Aturar Servidor HTTP"
+msgstr "Atura el servidor HTTP"
#: platform/javascript/export/export.cpp
msgid "Run in Browser"
@@ -12818,7 +12847,15 @@ msgid "This node has been deprecated. Use AnimationTree instead."
msgstr ""
#: scene/gui/color_picker.cpp
-msgid "Pick a color from the screen."
+msgid ""
+"Color: #%s\n"
+"LMB: Set color\n"
+"RMB: Remove preset"
+msgstr ""
+
+#: scene/gui/color_picker.cpp
+#, fuzzy
+msgid "Pick a color from the editor window."
msgstr "Trieu un color de la pantalla."
#: scene/gui/color_picker.cpp
@@ -12940,6 +12977,12 @@ msgstr ""
msgid "Constants cannot be modified."
msgstr "Les constants no es poden modificar."
+#~ msgid "Project export failed with error code %d."
+#~ msgstr "L'exportació del projecte ha fallat amb el codi d'error %d."
+
+#~ msgid "Password:"
+#~ msgstr "Contrasenya:"
+
#~ msgid "A digit cannot be the first character in a Identifier segment."
#~ msgstr "Un dígit no pot ser el primer caràcter en un segment Identificador."
@@ -13258,9 +13301,6 @@ msgstr "Les constants no es poden modificar."
#~ msgid "Create folder"
#~ msgstr "Crea un Directori"
-#~ msgid "Already existing"
-#~ msgstr "Ja existeix"
-
#~ msgid "Custom Node"
#~ msgstr "Node Personalitzat"
@@ -13309,10 +13349,6 @@ msgstr "Les constants no es poden modificar."
#~ "PathFollow2D només funciona si s'estableix com a fill d'un node Path2D."
#, fuzzy
-#~ msgid "Split already exists."
-#~ msgstr "L'Acció '%s' ja existeix!"
-
-#, fuzzy
#~ msgid "Add Split"
#~ msgstr "Afegeix un punt"
diff --git a/editor/translations/cs.po b/editor/translations/cs.po
index 3d6a2fe03f..b1c4a67f51 100644
--- a/editor/translations/cs.po
+++ b/editor/translations/cs.po
@@ -16,12 +16,13 @@
# 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.
msgid ""
msgstr ""
"Project-Id-Version: Godot Engine editor\n"
"POT-Creation-Date: \n"
-"PO-Revision-Date: 2019-12-27 15:52+0000\n"
-"Last-Translator: David Kubeš <kubesdavid@email.cz>\n"
+"PO-Revision-Date: 2020-01-03 21:21+0000\n"
+"Last-Translator: Emil Jiří Tywoniak <emil.tywoniak@gmail.com>\n"
"Language-Team: Czech <https://hosted.weblate.org/projects/godot-engine/godot/"
"cs/>\n"
"Language: cs\n"
@@ -39,7 +40,7 @@ msgstr ""
#: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp
msgid "Expected a string of length 1 (a character)."
-msgstr ""
+msgstr "OÄekáván Å™etÄ›zec o délce 1 (znak)."
#: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp
#: modules/mono/glue/gd_glue.cpp
@@ -53,7 +54,8 @@ msgstr "Neplatný vstup %i (neprošel) ve výrazu"
#: core/math/expression.cpp
msgid "self can't be used because instance is null (not passed)"
-msgstr "self nemůže být použito, protože instance je null (neprošla)"
+msgstr ""
+"\"self\" nemůže být použito, protože instance je \"null\" (není předána)"
#: core/math/expression.cpp
msgid "Invalid operands to operator %s, %s and %s."
@@ -145,35 +147,35 @@ msgstr "Přesunout body Bézierovy křivky"
#: editor/animation_bezier_editor.cpp editor/animation_track_editor.cpp
msgid "Anim Duplicate Keys"
-msgstr "Animace: duplikovat klíÄe"
+msgstr "Animace: Duplikovat klíÄe"
#: editor/animation_bezier_editor.cpp editor/animation_track_editor.cpp
msgid "Anim Delete Keys"
-msgstr "Animace: smazat klíÄe"
+msgstr "Animace: Smazat klíÄe"
#: editor/animation_track_editor.cpp
msgid "Anim Change Keyframe Time"
-msgstr "Animace: ZmÄ›nit Äas klíÄového snímku"
+msgstr "Animace: ZmÄ›na Äasu klíÄového snímku"
#: editor/animation_track_editor.cpp
msgid "Anim Change Transition"
-msgstr "Animace: změna přechodu"
+msgstr "Animace: Změna přechodu"
#: editor/animation_track_editor.cpp
msgid "Anim Change Transform"
-msgstr "Animace: změna transformace"
+msgstr "Animace: Změna transformace"
#: editor/animation_track_editor.cpp
msgid "Anim Change Keyframe Value"
-msgstr "Animace: ZmÄ›nit hodnotu klíÄového snímku"
+msgstr "Animace: ZmÄ›na hodnoty klíÄového snímku"
#: editor/animation_track_editor.cpp
msgid "Anim Change Call"
-msgstr "Animace: změna volání"
+msgstr "Animace: Změna volání"
#: editor/animation_track_editor.cpp
msgid "Anim Multi Change Keyframe Time"
-msgstr "Animace: ZmÄ›nit Äas klíÄových snímků"
+msgstr "Animace: ZmÄ›na Äasu klíÄových snímků"
#: editor/animation_track_editor.cpp
msgid "Anim Multi Change Transition"
@@ -431,7 +433,7 @@ msgstr "Není možné přidat novou stopu bez kořenového uzlu"
#: editor/animation_track_editor.cpp
msgid "Invalid track for Bezier (no suitable sub-properties)"
-msgstr ""
+msgstr "Neplatná stopa pro Bezier (žádné vhodné podvlastnosti)"
#: editor/animation_track_editor.cpp
msgid "Add Bezier Track"
@@ -831,7 +833,7 @@ msgstr "Odloženě"
#: editor/connections_dialog.cpp
msgid ""
"Defers the signal, storing it in a queue and only firing it at idle time."
-msgstr ""
+msgstr "Odkládá signál, ukládá do fronty a jen spouÅ¡tí pÅ™i neÄinnosti."
#: editor/connections_dialog.cpp
msgid "Oneshot"
@@ -1174,7 +1176,6 @@ msgid "Third-party Licenses"
msgstr "Licence třetích stran"
#: editor/editor_about.cpp
-#, fuzzy
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 "
@@ -1183,8 +1184,8 @@ msgid ""
msgstr ""
"Godot Engine závisí na volně dostupných a open source knihovnách od třetích "
"stran; všechny jsou kompatibilní s podmínkami jeho MIT licence. Následuje "
-"vyÄerpávající seznam tÄ›chto komponent tÅ™etích stran s jejich přísluÅ¡nými "
-"popisy autorských práv a s licenÄními podmínkami."
+"plný výÄet tÄ›chto komponent tÅ™etích stran s jejich přísluÅ¡nými popisy "
+"autorských práv a s licenÄními podmínkami."
#: editor/editor_about.cpp
msgid "All Components"
@@ -1203,10 +1204,24 @@ msgid "Error opening package file, not in ZIP format."
msgstr "NepodaÅ™ilo se otevřít balíÄek, není ve formátu ZIP."
#: editor/editor_asset_installer.cpp
+#, fuzzy
+msgid "%s (Already Exists)"
+msgstr "Již existující"
+
+#: editor/editor_asset_installer.cpp
msgid "Uncompressing Assets"
msgstr "Dekomprese uživatelského obsahu"
#: editor/editor_asset_installer.cpp editor/project_manager.cpp
+msgid "The following files failed extraction from package:"
+msgstr ""
+
+#: editor/editor_asset_installer.cpp
+#, fuzzy
+msgid "And %s more files."
+msgstr "%d více souborů"
+
+#: editor/editor_asset_installer.cpp editor/project_manager.cpp
msgid "Package installed successfully!"
msgstr "BalíÄek byl úspěšnÄ› nainstalován!"
@@ -1215,6 +1230,11 @@ msgstr "BalíÄek byl úspěšnÄ› nainstalován!"
msgid "Success!"
msgstr "Úspěch!"
+#: editor/editor_asset_installer.cpp
+#, fuzzy
+msgid "Package Contents:"
+msgstr "Obsah:"
+
#: editor/editor_asset_installer.cpp editor/editor_node.cpp
msgid "Install"
msgstr "Instalovat"
@@ -1269,7 +1289,7 @@ msgstr "Smazat Bus efekt"
#: editor/editor_audio_buses.cpp
msgid "Drag & drop to rearrange."
-msgstr ""
+msgstr "Přetažením uspořádejte."
#: editor/editor_audio_buses.cpp
msgid "Solo"
@@ -1353,6 +1373,11 @@ msgid "Invalid file, not an audio bus layout."
msgstr "Neplatný soubor, neni to rozložení Audio Busu."
#: editor/editor_audio_buses.cpp
+#, fuzzy
+msgid "Error saving file: %s"
+msgstr "Chyba při ukládání souboru!"
+
+#: editor/editor_audio_buses.cpp
msgid "Add Bus"
msgstr "Přidat bus"
@@ -1384,11 +1409,11 @@ msgstr "NaÄíst výchozí"
#: editor/editor_audio_buses.cpp
msgid "Load the default Bus Layout."
-msgstr ""
+msgstr "NaÄíst výchozí rozvržení sbÄ›rnice."
#: editor/editor_audio_buses.cpp
msgid "Create a new Bus Layout."
-msgstr ""
+msgstr "Vytvořit nové rozvržení sběrnice."
#: editor/editor_autoload_settings.cpp
msgid "Invalid name."
@@ -1399,21 +1424,16 @@ msgid "Valid characters:"
msgstr "Platné znaky:"
#: editor/editor_autoload_settings.cpp
-#, fuzzy
msgid "Must not collide with an existing engine class name."
-msgstr "Neplatný název. Nesmí kolidovat s existující názvem třídy enginu."
+msgstr "Nesmí kolidovat s existující názvem třídy enginu."
#: editor/editor_autoload_settings.cpp
-#, fuzzy
msgid "Must not collide with an existing built-in type name."
-msgstr ""
-"Neplatný název. Nesmí kolidovat s existujícím jménem zabudovaného typu."
+msgstr "Nesmí kolidovat s existujícím jménem zabudovaného typu."
#: editor/editor_autoload_settings.cpp
-#, fuzzy
msgid "Must not collide with an existing global constant name."
-msgstr ""
-"Neplatný název. Nesmí kolidovat s existujícím názvem globální konstanty."
+msgstr "Nesmí kolidovat s existujícím názvem globální konstanty."
#: editor/editor_autoload_settings.cpp
msgid "Keyword cannot be used as an autoload name."
@@ -1563,12 +1583,16 @@ msgstr ""
"Etc 2' v nastaveních projektu."
#: editor/editor_export.cpp
+#, fuzzy
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 ""
+"Cílová platforma vyžaduje kompresi textur 'ETC' pro použití GLES2 jako "
+"zálohy. Povolte 'Import Etc' v nastaveních projektu, nebo vypněte 'Driver "
+"Fallback Enabled'."
#: editor/editor_export.cpp platform/android/export/export.cpp
#: platform/iphone/export/export.cpp platform/javascript/export/export.cpp
@@ -1595,23 +1619,20 @@ msgid "3D Editor"
msgstr "3D Editor"
#: editor/editor_feature_profile.cpp
-#, fuzzy
msgid "Script Editor"
-msgstr "Otevřít editor skriptů"
+msgstr "Editor skriptů"
#: editor/editor_feature_profile.cpp
msgid "Asset Library"
msgstr "Knihovna assetů"
#: editor/editor_feature_profile.cpp
-#, fuzzy
msgid "Scene Tree Editing"
-msgstr "Strom scény (uzly):"
+msgstr "Úpravy stromu scény"
#: editor/editor_feature_profile.cpp
-#, fuzzy
msgid "Import Dock"
-msgstr "Importovat"
+msgstr "Importovat dok"
#: editor/editor_feature_profile.cpp
#, fuzzy
@@ -1654,14 +1675,12 @@ msgid "Class Options:"
msgstr "Možnosti třídy:"
#: editor/editor_feature_profile.cpp
-#, fuzzy
msgid "Enable Contextual Editor"
-msgstr "Otevřít další editor"
+msgstr "Aktivovat kontextový editor"
#: editor/editor_feature_profile.cpp
-#, fuzzy
msgid "Enabled Properties:"
-msgstr "Vlastnosti:"
+msgstr "Aktivní vlastnosti:"
#: editor/editor_feature_profile.cpp
msgid "Enabled Features:"
@@ -1694,9 +1713,8 @@ msgid "Current Profile:"
msgstr "Aktuální profil:"
#: editor/editor_feature_profile.cpp
-#, fuzzy
msgid "Make Current"
-msgstr "Aktuální:"
+msgstr "Zvolit jako aktuální"
#: editor/editor_feature_profile.cpp
#: editor/plugins/animation_player_editor_plugin.cpp
@@ -1860,18 +1878,16 @@ msgid "Go to next folder."
msgstr "Přejít do další složky."
#: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp
-#, fuzzy
msgid "Go to parent folder."
-msgstr "Jít na nadřazenou složku"
+msgstr "Přejít do nadřazené složky."
#: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp
msgid "Refresh files."
msgstr "Obnovit soubory."
#: editor/editor_file_dialog.cpp
-#, fuzzy
msgid "(Un)favorite current folder."
-msgstr "Nelze vytvořit složku."
+msgstr "Přidat/odebrat složku z oblíbených"
#: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp
#, fuzzy
@@ -2164,10 +2180,6 @@ msgid "New Window"
msgstr "Nové okno"
#: editor/editor_node.cpp
-msgid "Project export failed with error code %d."
-msgstr "Export projektu selhal s chybovým kódem %d."
-
-#: editor/editor_node.cpp
msgid "Imported resources can't be saved."
msgstr "Nelze uložit importované zdroje."
@@ -3081,10 +3093,6 @@ msgstr "Importovat Å¡ablony ze ZIP souboru"
msgid "Template Package"
msgstr "Správce exportních šablon"
-#: editor/editor_node.cpp editor/project_export.cpp
-msgid "Export Project"
-msgstr "Exportovat projekt"
-
#: editor/editor_node.cpp
msgid "Export Library"
msgstr "Exportovat knihovnu"
@@ -3094,10 +3102,6 @@ msgid "Merge With Existing"
msgstr "SlouÄit s existující"
#: editor/editor_node.cpp
-msgid "Password:"
-msgstr "Heslo:"
-
-#: editor/editor_node.cpp
msgid "Open & Run a Script"
msgstr "Otevřít a spustit skript"
@@ -5760,6 +5764,22 @@ msgstr "Emisní maska"
#: 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
+#, fuzzy
+msgid "Directed Border Pixels"
+msgstr "Složky a soubory:"
+
+#: editor/plugins/cpu_particles_2d_editor_plugin.cpp
+#: editor/plugins/particles_2d_editor_plugin.cpp
msgid "Capture from Pixel"
msgstr ""
@@ -9586,6 +9606,10 @@ msgid "Export PCK/Zip"
msgstr "Exportovat PCK/Zip"
#: editor/project_export.cpp
+msgid "Export Project"
+msgstr "Exportovat projekt"
+
+#: editor/project_export.cpp
msgid "Export mode?"
msgstr "Režim exportu?"
@@ -9677,10 +9701,6 @@ msgid "Couldn't create project.godot in project path."
msgstr ""
#: editor/project_manager.cpp
-msgid "The following files failed extraction from package:"
-msgstr ""
-
-#: editor/project_manager.cpp
msgid "Rename Project"
msgstr "Přejmenovat projekt"
@@ -10903,6 +10923,11 @@ msgstr "NaÄíst existující soubor skriptu"
#: editor/script_create_dialog.cpp
#, fuzzy
+msgid "Script file already exists."
+msgstr "Akce '%s' již existuje!"
+
+#: editor/script_create_dialog.cpp
+#, fuzzy
msgid "Class Name:"
msgstr "Jméno třídy"
@@ -12574,7 +12599,15 @@ msgid "This node has been deprecated. Use AnimationTree instead."
msgstr ""
#: scene/gui/color_picker.cpp
-msgid "Pick a color from the screen."
+msgid ""
+"Color: #%s\n"
+"LMB: Set color\n"
+"RMB: Remove preset"
+msgstr ""
+
+#: scene/gui/color_picker.cpp
+#, fuzzy
+msgid "Pick a color from the editor window."
msgstr "Vyberte barvu z obrazovky."
#: scene/gui/color_picker.cpp
@@ -12693,6 +12726,12 @@ msgstr ""
msgid "Constants cannot be modified."
msgstr "Konstanty není možné upravovat."
+#~ msgid "Project export failed with error code %d."
+#~ msgstr "Export projektu selhal s chybovým kódem %d."
+
+#~ msgid "Password:"
+#~ msgstr "Heslo:"
+
#~ msgid "Pause the scene"
#~ msgstr "Pozastavit scénu"
@@ -12931,9 +12970,6 @@ msgstr "Konstanty není možné upravovat."
#~ msgid "Create folder"
#~ msgstr "Vytvořit složku"
-#~ msgid "Already existing"
-#~ msgstr "Již existující"
-
#~ msgid "Custom Node"
#~ msgstr "Vlastní uzel"
@@ -12972,10 +13008,6 @@ msgstr "Konstanty není možné upravovat."
#~ msgstr "OrientedPathFollow funguje pouze když je dítětem uzlu Path."
#, fuzzy
-#~ msgid "Split already exists."
-#~ msgstr "Akce '%s' již existuje!"
-
-#, fuzzy
#~ msgid "Add Split"
#~ msgstr "Přidat bod"
diff --git a/editor/translations/da.po b/editor/translations/da.po
index 513b38e5f7..4c2976812c 100644
--- a/editor/translations/da.po
+++ b/editor/translations/da.po
@@ -1241,10 +1241,24 @@ msgid "Error opening package file, not in ZIP format."
msgstr "Fejl ved åbning af pakke fil, ikke i zip format."
#: editor/editor_asset_installer.cpp
+#, fuzzy
+msgid "%s (Already Exists)"
+msgstr "Autoload '%s' eksisterer allerede!"
+
+#: editor/editor_asset_installer.cpp
msgid "Uncompressing Assets"
msgstr "Udpakker Aktiver"
#: editor/editor_asset_installer.cpp editor/project_manager.cpp
+msgid "The following files failed extraction from package:"
+msgstr ""
+
+#: editor/editor_asset_installer.cpp
+#, fuzzy
+msgid "And %s more files."
+msgstr "%d flere filer"
+
+#: editor/editor_asset_installer.cpp editor/project_manager.cpp
msgid "Package installed successfully!"
msgstr "Pakke installeret med succes!"
@@ -1253,6 +1267,11 @@ msgstr "Pakke installeret med succes!"
msgid "Success!"
msgstr "Succes!"
+#: editor/editor_asset_installer.cpp
+#, fuzzy
+msgid "Package Contents:"
+msgstr "Indhold:"
+
#: editor/editor_asset_installer.cpp editor/editor_node.cpp
msgid "Install"
msgstr "Installér"
@@ -1392,6 +1411,11 @@ msgid "Invalid file, not an audio bus layout."
msgstr "Ugyldig fil, er ikke et audio bus layout."
#: editor/editor_audio_buses.cpp
+#, fuzzy
+msgid "Error saving file: %s"
+msgstr "Fejl, kan ikke gemme TileSet!"
+
+#: editor/editor_audio_buses.cpp
msgid "Add Bus"
msgstr "Tilføj Bus"
@@ -2227,10 +2251,6 @@ msgid "New Window"
msgstr ""
#: editor/editor_node.cpp
-msgid "Project export failed with error code %d."
-msgstr "Projekt eksport fejlede med fejlkode %d."
-
-#: editor/editor_node.cpp
msgid "Imported resources can't be saved."
msgstr ""
@@ -3152,10 +3172,6 @@ msgstr "Importér Skabeloner Fra ZIP Fil"
msgid "Template Package"
msgstr "Eksporter Skabelon Manager"
-#: editor/editor_node.cpp editor/project_export.cpp
-msgid "Export Project"
-msgstr "Eksporter Projekt"
-
#: editor/editor_node.cpp
msgid "Export Library"
msgstr "Eksporter Bibliotek"
@@ -3165,10 +3181,6 @@ msgid "Merge With Existing"
msgstr "Flet Med Eksisterende"
#: editor/editor_node.cpp
-msgid "Password:"
-msgstr "Kodeord:"
-
-#: editor/editor_node.cpp
msgid "Open & Run a Script"
msgstr "Åben & Kør et Script"
@@ -5909,6 +5921,22 @@ 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
+#, fuzzy
+msgid "Directed Border Pixels"
+msgstr "Mapper & Filer:"
+
+#: editor/plugins/cpu_particles_2d_editor_plugin.cpp
+#: editor/plugins/particles_2d_editor_plugin.cpp
msgid "Capture from Pixel"
msgstr ""
@@ -9726,6 +9754,10 @@ msgid "Export PCK/Zip"
msgstr ""
#: editor/project_export.cpp
+msgid "Export Project"
+msgstr "Eksporter Projekt"
+
+#: editor/project_export.cpp
#, fuzzy
msgid "Export mode?"
msgstr "Eksporter Projekt"
@@ -9821,10 +9853,6 @@ msgid "Couldn't create project.godot in project path."
msgstr ""
#: editor/project_manager.cpp
-msgid "The following files failed extraction from package:"
-msgstr ""
-
-#: editor/project_manager.cpp
msgid "Rename Project"
msgstr "Omdøb Projekt"
@@ -11050,6 +11078,11 @@ msgstr "Indlæs et eksisterende Bus Layout."
#: editor/script_create_dialog.cpp
#, fuzzy
+msgid "Script file already exists."
+msgstr "Autoload '%s' eksisterer allerede!"
+
+#: editor/script_create_dialog.cpp
+#, fuzzy
msgid "Class Name:"
msgstr "Klasse:"
@@ -12709,7 +12742,14 @@ msgid "This node has been deprecated. Use AnimationTree instead."
msgstr ""
#: scene/gui/color_picker.cpp
-msgid "Pick a color from the screen."
+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
@@ -12824,6 +12864,12 @@ msgstr ""
msgid "Constants cannot be modified."
msgstr "Konstanter kan ikke ændres."
+#~ msgid "Project export failed with error code %d."
+#~ msgstr "Projekt eksport fejlede med fejlkode %d."
+
+#~ msgid "Password:"
+#~ msgstr "Kodeord:"
+
#~ msgid "Pause the scene"
#~ msgstr "Sæt scenen på pause"
@@ -13005,10 +13051,6 @@ msgstr "Konstanter kan ikke ændres."
#~ "PathFollow2D virker kun, når den angives som et barn af en Path2D node."
#, fuzzy
-#~ msgid "Split already exists."
-#~ msgstr "Autoload '%s' eksisterer allerede!"
-
-#, fuzzy
#~ msgid "Add Split"
#~ msgstr "Tilføj punkt"
diff --git a/editor/translations/de.po b/editor/translations/de.po
index 706bab3fc3..d15b7a5b04 100644
--- a/editor/translations/de.po
+++ b/editor/translations/de.po
@@ -23,7 +23,7 @@
# Peter Friedland <peter_friedland@gmx.de>, 2016.
# No need for a name <endoplasmatik@gmx.net>, 2016.
# Sönke <me@eknoes.de>, 2018.
-# So Wieso <sowieso@dukun.de>, 2016-2018, 2019.
+# So Wieso <sowieso@dukun.de>, 2016-2018, 2019, 2020.
# Tim Schellenberg <smwleod@gmail.com>, 2017.
# Timo Schwarzer <account@timoschwarzer.com>, 2016-2018.
# viernullvier <hannes.breul+github@gmail.com>, 2016.
@@ -52,7 +52,7 @@ msgid ""
msgstr ""
"Project-Id-Version: Godot Engine editor\n"
"POT-Creation-Date: \n"
-"PO-Revision-Date: 2019-12-23 17:07+0000\n"
+"PO-Revision-Date: 2020-01-03 21:21+0000\n"
"Last-Translator: So Wieso <sowieso@dukun.de>\n"
"Language-Team: German <https://hosted.weblate.org/projects/godot-engine/"
"godot/de/>\n"
@@ -463,7 +463,7 @@ msgstr "Ohne eine Wurzel kann keine neue Spur hinzugefügt werden"
#: editor/animation_track_editor.cpp
msgid "Invalid track for Bezier (no suitable sub-properties)"
-msgstr ""
+msgstr "Spur ungültig als Bezier (keine passenden Unter-Eigenschaften)"
#: editor/animation_track_editor.cpp
msgid "Add Bezier Track"
@@ -1242,10 +1242,24 @@ msgid "Error opening package file, not in ZIP format."
msgstr "Fehler beim Öffnen der Paketdatei, kein ZIP-Format."
#: editor/editor_asset_installer.cpp
+#, fuzzy
+msgid "%s (Already Exists)"
+msgstr "Existiert bereits"
+
+#: editor/editor_asset_installer.cpp
msgid "Uncompressing Assets"
msgstr "Inhalte werden entpackt"
#: editor/editor_asset_installer.cpp editor/project_manager.cpp
+msgid "The following files failed extraction from package:"
+msgstr "Die folgenden Dateien ließen sich nicht aus dem Paket extrahieren:"
+
+#: editor/editor_asset_installer.cpp
+#, fuzzy
+msgid "And %s more files."
+msgstr "%d weitere Datei(en)"
+
+#: editor/editor_asset_installer.cpp editor/project_manager.cpp
msgid "Package installed successfully!"
msgstr "Paket wurde erfolgreich installiert!"
@@ -1254,6 +1268,11 @@ msgstr "Paket wurde erfolgreich installiert!"
msgid "Success!"
msgstr "Geschafft!"
+#: editor/editor_asset_installer.cpp
+#, fuzzy
+msgid "Package Contents:"
+msgstr "Inhalt:"
+
#: editor/editor_asset_installer.cpp editor/editor_node.cpp
msgid "Install"
msgstr "Installieren"
@@ -1392,6 +1411,11 @@ msgid "Invalid file, not an audio bus layout."
msgstr "Ungültige Datei, kein Audiobus-Layout."
#: editor/editor_audio_buses.cpp
+#, fuzzy
+msgid "Error saving file: %s"
+msgstr "Fehler beim Speichern der Datei!"
+
+#: editor/editor_audio_buses.cpp
msgid "Add Bus"
msgstr "Audiobus hinzufügen"
@@ -2044,9 +2068,8 @@ msgid "Case Sensitive"
msgstr "Groß-/Kleinschreibung beachten"
#: editor/editor_help_search.cpp
-#, fuzzy
msgid "Show Hierarchy"
-msgstr "Helfer anzeigen"
+msgstr "Rangordnung anzeigen"
#: editor/editor_help_search.cpp
msgid "Display All"
@@ -2085,9 +2108,8 @@ msgid "Class"
msgstr "Klasse"
#: editor/editor_help_search.cpp
-#, fuzzy
msgid "Method"
-msgstr "Methoden"
+msgstr "Methode"
#: editor/editor_help_search.cpp editor/plugins/script_text_editor.cpp
msgid "Signal"
@@ -2098,14 +2120,12 @@ msgid "Constant"
msgstr "Konstant"
#: editor/editor_help_search.cpp
-#, fuzzy
msgid "Property"
-msgstr "Eigenschaft:"
+msgstr "Eigenschaft"
#: editor/editor_help_search.cpp
-#, fuzzy
msgid "Theme Property"
-msgstr "Motiv-Eigenschaften"
+msgstr "Motiv-Eigenschaft"
#: editor/editor_inspector.cpp editor/project_settings_editor.cpp
msgid "Property:"
@@ -2188,10 +2208,6 @@ msgid "New Window"
msgstr "Neues Fenster"
#: editor/editor_node.cpp
-msgid "Project export failed with error code %d."
-msgstr "Projekt-Export ist fehlgeschlagen mit Fehlercode %d."
-
-#: editor/editor_node.cpp
msgid "Imported resources can't be saved."
msgstr "Importierte Ressourcen können nicht abgespeichert werden."
@@ -3120,10 +3136,6 @@ msgstr "Vorlagen aus ZIP-Datei importieren"
msgid "Template Package"
msgstr "Vorlagenpaket"
-#: editor/editor_node.cpp editor/project_export.cpp
-msgid "Export Project"
-msgstr "Projekt exportieren"
-
#: editor/editor_node.cpp
msgid "Export Library"
msgstr "Bibliothek exportieren"
@@ -3133,10 +3145,6 @@ msgid "Merge With Existing"
msgstr "Mit existierendem vereinen"
#: editor/editor_node.cpp
-msgid "Password:"
-msgstr "Passwort:"
-
-#: editor/editor_node.cpp
msgid "Open & Run a Script"
msgstr "Skript öffnen und ausführen"
@@ -3501,13 +3509,14 @@ msgid "Importing:"
msgstr "Importiere:"
#: editor/export_template_manager.cpp
-#, fuzzy
msgid "Error getting the list of mirrors."
-msgstr "Fehler beim erstellen des Signaturobjekts."
+msgstr "Fehler beim Laden der Spiegelserver."
#: editor/export_template_manager.cpp
msgid "Error parsing JSON of mirror list. Please report this issue!"
msgstr ""
+"Fehler beim Einlesen des JSON-Formats der Spiegelserverliste. Bitte diesen "
+"Fehler melden!"
#: editor/export_template_manager.cpp
msgid ""
@@ -4696,9 +4705,8 @@ msgid "Move Node"
msgstr "Node verschieben"
#: editor/plugins/animation_state_machine_editor.cpp
-#, fuzzy
msgid "Transition exists!"
-msgstr "Übergänge"
+msgstr "Ãœbergang existiert bereits!"
#: editor/plugins/animation_state_machine_editor.cpp
msgid "Add Transition"
@@ -5778,6 +5786,23 @@ msgstr "Emissionsmaske"
#: editor/plugins/cpu_particles_2d_editor_plugin.cpp
#: editor/plugins/particles_2d_editor_plugin.cpp
+#, fuzzy
+msgid "Solid Pixels"
+msgstr "Schrumpfen (Pixel): "
+
+#: 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
+#, fuzzy
+msgid "Directed Border Pixels"
+msgstr "Verzeichnisse & Dateien:"
+
+#: editor/plugins/cpu_particles_2d_editor_plugin.cpp
+#: editor/plugins/particles_2d_editor_plugin.cpp
msgid "Capture from Pixel"
msgstr "Von Pixel aufnehmen"
@@ -6004,18 +6029,19 @@ msgstr "Umrissgröße:"
#: editor/plugins/mesh_instance_editor_plugin.cpp
msgid "UV Channel Debug"
-msgstr ""
+msgstr "UV-Channel-Debug"
#: editor/plugins/mesh_library_editor_plugin.cpp
msgid "Remove item %d?"
msgstr "Element %d entfernen?"
#: editor/plugins/mesh_library_editor_plugin.cpp
-#, fuzzy
msgid ""
"Update from existing scene?:\n"
"%s"
-msgstr "Aus Szene aktualisieren"
+msgstr ""
+"Aus bestehender Szene aktualisieren?:\n"
+"%s"
#: editor/plugins/mesh_library_editor_plugin.cpp
msgid "Mesh Library"
@@ -7575,9 +7601,8 @@ msgid "Create Mesh2D"
msgstr "Mesh2D erzeugen"
#: editor/plugins/sprite_editor_plugin.cpp
-#, fuzzy
msgid "Mesh2D Preview"
-msgstr "Mesh-Vorschauen erzeugen"
+msgstr "Mesh2D-Vorschau"
#: editor/plugins/sprite_editor_plugin.cpp
msgid "Create Polygon2D"
@@ -7585,25 +7610,23 @@ msgstr "Polygon2D erzeugen"
#: editor/plugins/sprite_editor_plugin.cpp
msgid "Polygon2D Preview"
-msgstr ""
+msgstr "Polygon2D-Vorschau"
#: editor/plugins/sprite_editor_plugin.cpp
msgid "Create CollisionPolygon2D"
msgstr "CollisionPolygon2D erzeugen"
#: editor/plugins/sprite_editor_plugin.cpp
-#, fuzzy
msgid "CollisionPolygon2D Preview"
-msgstr "CollisionPolygon2D erzeugen"
+msgstr "CollisionPolygon2D-Vorschau"
#: editor/plugins/sprite_editor_plugin.cpp
msgid "Create LightOccluder2D"
msgstr "LightOccluder2D erzeugen"
#: editor/plugins/sprite_editor_plugin.cpp
-#, fuzzy
msgid "LightOccluder2D Preview"
-msgstr "LightOccluder2D erzeugen"
+msgstr "LightOccluder2D-Vorschau"
#: editor/plugins/sprite_editor_plugin.cpp
msgid "Sprite is empty!"
@@ -7684,9 +7707,8 @@ msgid "Add Frame"
msgstr "Frame hinzufügen"
#: editor/plugins/sprite_frames_editor_plugin.cpp
-#, fuzzy
msgid "Unable to load images"
-msgstr "Bild konnte nicht geladen werden:"
+msgstr "Bilder konnten nicht geladen werden"
#: editor/plugins/sprite_frames_editor_plugin.cpp
msgid "ERROR: Couldn't load frame resource!"
@@ -8378,14 +8400,12 @@ msgid "Edit Tile Z Index"
msgstr "bearbeite Kachel Z Index"
#: editor/plugins/tile_set_editor_plugin.cpp
-#, fuzzy
msgid "Make Convex"
-msgstr "Polygon konvex machen"
+msgstr "Konvex machen"
#: editor/plugins/tile_set_editor_plugin.cpp
-#, fuzzy
msgid "Make Concave"
-msgstr "Polygon konkav machen"
+msgstr "Konkav machen"
#: editor/plugins/tile_set_editor_plugin.cpp
msgid "Create Collision Polygon"
@@ -9545,6 +9565,10 @@ msgid "Export PCK/Zip"
msgstr "Exportiere PCK/Zip"
#: editor/project_export.cpp
+msgid "Export Project"
+msgstr "Projekt exportieren"
+
+#: editor/project_export.cpp
msgid "Export mode?"
msgstr "Export-Modus?"
@@ -9638,10 +9662,6 @@ msgid "Couldn't create project.godot in project path."
msgstr "Konnte project.godot im Projektpfad nicht erzeugen."
#: editor/project_manager.cpp
-msgid "The following files failed extraction from package:"
-msgstr "Die folgenden Dateien ließen sich nicht aus dem Paket extrahieren:"
-
-#: editor/project_manager.cpp
msgid "Rename Project"
msgstr "Projekt umbenennen"
@@ -10887,6 +10907,11 @@ msgid "Will load an existing script file."
msgstr "Dies wird eine bestehende Skriptdatei laden."
#: editor/script_create_dialog.cpp
+#, fuzzy
+msgid "Script file already exists."
+msgstr "Teilung existiert bereits."
+
+#: editor/script_create_dialog.cpp
msgid "Class Name:"
msgstr "Klassenname:"
@@ -11337,9 +11362,8 @@ msgid "Cursor Clear Rotation"
msgstr "Rotation am Mauszeiger zurücksetzen"
#: modules/gridmap/grid_map_editor_plugin.cpp
-#, fuzzy
msgid "Paste Selects"
-msgstr "Auswahl löschen"
+msgstr "Auswahlen einfügen"
#: modules/gridmap/grid_map_editor_plugin.cpp
msgid "Clear Selection"
@@ -12582,7 +12606,15 @@ msgstr ""
"AnimationTree."
#: scene/gui/color_picker.cpp
-msgid "Pick a color from the screen."
+msgid ""
+"Color: #%s\n"
+"LMB: Set color\n"
+"RMB: Remove preset"
+msgstr ""
+
+#: scene/gui/color_picker.cpp
+#, fuzzy
+msgid "Pick a color from the editor window."
msgstr "Wählt eine Farbe vom Bildschirm aus."
#: scene/gui/color_picker.cpp
@@ -12709,6 +12741,12 @@ msgstr "Varyings können nur in Vertex-Funktion zugewiesen werden."
msgid "Constants cannot be modified."
msgstr "Konstanten können nicht verändert werden."
+#~ msgid "Project export failed with error code %d."
+#~ msgstr "Projekt-Export ist fehlgeschlagen mit Fehlercode %d."
+
+#~ msgid "Password:"
+#~ msgstr "Passwort:"
+
#~ msgid "Identifier segments must be of non-zero length."
#~ msgstr "Bezeichnersegmente dürfen keine Länge gleich Null haben."
@@ -13177,9 +13215,6 @@ msgstr "Konstanten können nicht verändert werden."
#~ msgid "Create folder"
#~ msgstr "Ordner erstellen"
-#~ msgid "Already existing"
-#~ msgstr "Existiert bereits"
-
#~ msgid "Custom Node"
#~ msgstr "Selbst-erstelltes Node"
@@ -13231,9 +13266,6 @@ msgstr "Konstanten können nicht verändert werden."
#~ msgid "Split can't form an existing edge."
#~ msgstr "Teilen kann keine existierende Kante erstellen."
-#~ msgid "Split already exists."
-#~ msgstr "Teilung existiert bereits."
-
#~ msgid "Add Split"
#~ msgstr "Teilung hinzufügen"
diff --git a/editor/translations/de_CH.po b/editor/translations/de_CH.po
index 8767ee664d..093718f019 100644
--- a/editor/translations/de_CH.po
+++ b/editor/translations/de_CH.po
@@ -1204,10 +1204,23 @@ msgid "Error opening package file, not in ZIP format."
msgstr ""
#: editor/editor_asset_installer.cpp
+msgid "%s (Already Exists)"
+msgstr ""
+
+#: editor/editor_asset_installer.cpp
msgid "Uncompressing Assets"
msgstr ""
#: editor/editor_asset_installer.cpp editor/project_manager.cpp
+msgid "The following files failed extraction from package:"
+msgstr ""
+
+#: editor/editor_asset_installer.cpp
+#, fuzzy
+msgid "And %s more files."
+msgstr "Node erstellen"
+
+#: editor/editor_asset_installer.cpp editor/project_manager.cpp
msgid "Package installed successfully!"
msgstr ""
@@ -1216,6 +1229,10 @@ msgstr ""
msgid "Success!"
msgstr ""
+#: editor/editor_asset_installer.cpp
+msgid "Package Contents:"
+msgstr ""
+
#: editor/editor_asset_installer.cpp editor/editor_node.cpp
msgid "Install"
msgstr ""
@@ -1359,6 +1376,11 @@ msgid "Invalid file, not an audio bus layout."
msgstr ""
#: editor/editor_audio_buses.cpp
+#, fuzzy
+msgid "Error saving file: %s"
+msgstr "Szene kann nicht gespeichert werden."
+
+#: editor/editor_audio_buses.cpp
msgid "Add Bus"
msgstr ""
@@ -2163,10 +2185,6 @@ msgid "New Window"
msgstr ""
#: editor/editor_node.cpp
-msgid "Project export failed with error code %d."
-msgstr ""
-
-#: editor/editor_node.cpp
msgid "Imported resources can't be saved."
msgstr ""
@@ -3036,10 +3054,6 @@ msgstr ""
msgid "Template Package"
msgstr "Ungültige Bilder löschen"
-#: editor/editor_node.cpp editor/project_export.cpp
-msgid "Export Project"
-msgstr "Projekt exportieren"
-
#: editor/editor_node.cpp
msgid "Export Library"
msgstr ""
@@ -3049,10 +3063,6 @@ msgid "Merge With Existing"
msgstr ""
#: editor/editor_node.cpp
-msgid "Password:"
-msgstr ""
-
-#: editor/editor_node.cpp
msgid "Open & Run a Script"
msgstr ""
@@ -5764,6 +5774,21 @@ msgstr "Emissions-Maske setzen"
#: 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 ""
@@ -9557,6 +9582,10 @@ msgid "Export PCK/Zip"
msgstr "Exportiere das Projekt PCK"
#: editor/project_export.cpp
+msgid "Export Project"
+msgstr "Projekt exportieren"
+
+#: editor/project_export.cpp
#, fuzzy
msgid "Export mode?"
msgstr "Projekt exportieren"
@@ -9656,10 +9685,6 @@ msgid "Couldn't create project.godot in project path."
msgstr "Die engine.cfg kann im Projektverzeichnis nicht erstellt werden."
#: editor/project_manager.cpp
-msgid "The following files failed extraction from package:"
-msgstr ""
-
-#: editor/project_manager.cpp
#, fuzzy
msgid "Rename Project"
msgstr "Neues Projekt erstellen"
@@ -10864,6 +10889,10 @@ msgid "Will load an existing script file."
msgstr ""
#: editor/script_create_dialog.cpp
+msgid "Script file already exists."
+msgstr ""
+
+#: editor/script_create_dialog.cpp
msgid "Class Name:"
msgstr ""
@@ -12481,7 +12510,14 @@ msgid "This node has been deprecated. Use AnimationTree instead."
msgstr ""
#: scene/gui/color_picker.cpp
-msgid "Pick a color from the screen."
+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
diff --git a/editor/translations/editor.pot b/editor/translations/editor.pot
index 87e60cba52..bae7df17e2 100644
--- a/editor/translations/editor.pot
+++ b/editor/translations/editor.pot
@@ -1150,10 +1150,22 @@ msgid "Error opening package file, not in ZIP format."
msgstr ""
#: editor/editor_asset_installer.cpp
+msgid "%s (Already Exists)"
+msgstr ""
+
+#: editor/editor_asset_installer.cpp
msgid "Uncompressing Assets"
msgstr ""
#: editor/editor_asset_installer.cpp editor/project_manager.cpp
+msgid "The following files failed extraction from package:"
+msgstr ""
+
+#: editor/editor_asset_installer.cpp
+msgid "And %s more files."
+msgstr ""
+
+#: editor/editor_asset_installer.cpp editor/project_manager.cpp
msgid "Package installed successfully!"
msgstr ""
@@ -1162,6 +1174,10 @@ msgstr ""
msgid "Success!"
msgstr ""
+#: editor/editor_asset_installer.cpp
+msgid "Package Contents:"
+msgstr ""
+
#: editor/editor_asset_installer.cpp editor/editor_node.cpp
msgid "Install"
msgstr ""
@@ -1300,6 +1316,10 @@ msgid "Invalid file, not an audio bus layout."
msgstr ""
#: editor/editor_audio_buses.cpp
+msgid "Error saving file: %s"
+msgstr ""
+
+#: editor/editor_audio_buses.cpp
msgid "Add Bus"
msgstr ""
@@ -2072,10 +2092,6 @@ msgid "New Window"
msgstr ""
#: editor/editor_node.cpp
-msgid "Project export failed with error code %d."
-msgstr ""
-
-#: editor/editor_node.cpp
msgid "Imported resources can't be saved."
msgstr ""
@@ -2914,10 +2930,6 @@ msgstr ""
msgid "Template Package"
msgstr ""
-#: editor/editor_node.cpp editor/project_export.cpp
-msgid "Export Project"
-msgstr ""
-
#: editor/editor_node.cpp
msgid "Export Library"
msgstr ""
@@ -2927,10 +2939,6 @@ msgid "Merge With Existing"
msgstr ""
#: editor/editor_node.cpp
-msgid "Password:"
-msgstr ""
-
-#: editor/editor_node.cpp
msgid "Open & Run a Script"
msgstr ""
@@ -5492,6 +5500,21 @@ 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 ""
@@ -9108,6 +9131,10 @@ msgid "Export PCK/Zip"
msgstr ""
#: editor/project_export.cpp
+msgid "Export Project"
+msgstr ""
+
+#: editor/project_export.cpp
msgid "Export mode?"
msgstr ""
@@ -9198,10 +9225,6 @@ msgid "Couldn't create project.godot in project path."
msgstr ""
#: editor/project_manager.cpp
-msgid "The following files failed extraction from package:"
-msgstr ""
-
-#: editor/project_manager.cpp
msgid "Rename Project"
msgstr ""
@@ -10360,6 +10383,10 @@ msgid "Will load an existing script file."
msgstr ""
#: editor/script_create_dialog.cpp
+msgid "Script file already exists."
+msgstr ""
+
+#: editor/script_create_dialog.cpp
msgid "Class Name:"
msgstr ""
@@ -11885,7 +11912,14 @@ msgid "This node has been deprecated. Use AnimationTree instead."
msgstr ""
#: scene/gui/color_picker.cpp
-msgid "Pick a color from the screen."
+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
diff --git a/editor/translations/el.po b/editor/translations/el.po
index ad5d375d49..8c152332a2 100644
--- a/editor/translations/el.po
+++ b/editor/translations/el.po
@@ -6,12 +6,14 @@
# Georgios Katsanakis <geo.elgeo@gmail.com>, 2019.
# Overloaded <manoschool@yahoo.gr>, 2019.
# Eternal Death <eternaldeath0001@gmail.com>, 2019.
+# Overloaded @ Orama Interactive http://orama-interactive.com/ <manoschool@yahoo.gr>, 2020.
msgid ""
msgstr ""
"Project-Id-Version: Godot Engine editor\n"
"POT-Creation-Date: \n"
-"PO-Revision-Date: 2019-12-25 12:45+0000\n"
-"Last-Translator: Overloaded <manoschool@yahoo.gr>\n"
+"PO-Revision-Date: 2020-01-03 21:21+0000\n"
+"Last-Translator: Overloaded @ Orama Interactive http://orama-interactive."
+"com/ <manoschool@yahoo.gr>\n"
"Language-Team: Greek <https://hosted.weblate.org/projects/godot-engine/godot/"
"el/>\n"
"Language: el\n"
@@ -29,7 +31,7 @@ msgstr ""
#: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp
msgid "Expected a string of length 1 (a character)."
-msgstr ""
+msgstr "Αναμενόταν μια συμβολοσειÏά μήκους 1 (ένας χαÏακτήÏας)."
#: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp
#: modules/mono/glue/gd_glue.cpp
@@ -1198,10 +1200,24 @@ msgid "Error opening package file, not in ZIP format."
msgstr "Σφάλμα ανοίγματος αÏχείου πακέτου, δεν είναι σε μοÏφή ZIP."
#: editor/editor_asset_installer.cpp
+#, fuzzy
+msgid "%s (Already Exists)"
+msgstr "ΥπάÏχει ήδη"
+
+#: editor/editor_asset_installer.cpp
msgid "Uncompressing Assets"
msgstr "Αποσυμπίεση asset"
#: editor/editor_asset_installer.cpp editor/project_manager.cpp
+msgid "The following files failed extraction from package:"
+msgstr "Η εξαγωγή των ακόλουθων αÏχείων από το πακέτο απέτυχε:"
+
+#: editor/editor_asset_installer.cpp
+#, fuzzy
+msgid "And %s more files."
+msgstr "%d πεÏισσότεÏα αÏχεία"
+
+#: editor/editor_asset_installer.cpp editor/project_manager.cpp
msgid "Package installed successfully!"
msgstr "Το πακέτο εγκαταστάθηκε επιτυχώς!"
@@ -1210,6 +1226,11 @@ msgstr "Το πακέτο εγκαταστάθηκε επιτυχώς!"
msgid "Success!"
msgstr "Επιτυχία!"
+#: editor/editor_asset_installer.cpp
+#, fuzzy
+msgid "Package Contents:"
+msgstr "ΠεÏιεχόμενα:"
+
#: editor/editor_asset_installer.cpp editor/editor_node.cpp
msgid "Install"
msgstr "Εγκατάσταση"
@@ -1348,6 +1369,11 @@ msgid "Invalid file, not an audio bus layout."
msgstr "ΆκυÏο αÏχείο, δεν είναι διάταξη διαÏλων ήχου."
#: editor/editor_audio_buses.cpp
+#, fuzzy
+msgid "Error saving file: %s"
+msgstr "Σφάλμα αποθήκευσης αÏχείου!"
+
+#: editor/editor_audio_buses.cpp
msgid "Add Bus"
msgstr "ΠÏοσθήκη διαÏλου"
@@ -2144,10 +2170,6 @@ msgid "New Window"
msgstr "Îέο ΠαÏάθυÏο"
#: editor/editor_node.cpp
-msgid "Project export failed with error code %d."
-msgstr "Η εξαγωγή του έÏγου απέτυχε με κωδικό %d."
-
-#: editor/editor_node.cpp
msgid "Imported resources can't be saved."
msgstr "Οι εισαγμένοι πόÏοι δεν μποÏοÏν να αποθηκευτοÏν."
@@ -3081,10 +3103,6 @@ msgstr "Εισαγωγή Ï€ÏοτÏπων από αÏχείο ZIP"
msgid "Template Package"
msgstr "Πακέτο ΠÏοτÏπων"
-#: editor/editor_node.cpp editor/project_export.cpp
-msgid "Export Project"
-msgstr "Εξαγωγή έÏγου"
-
#: editor/editor_node.cpp
msgid "Export Library"
msgstr "Εξαγωγή βιβλιοθήκης"
@@ -3094,10 +3112,6 @@ msgid "Merge With Existing"
msgstr "Συγχώνευση με υπάÏχων"
#: editor/editor_node.cpp
-msgid "Password:"
-msgstr "Κωδικός:"
-
-#: editor/editor_node.cpp
msgid "Open & Run a Script"
msgstr "Άνοιξε & ΤÏέξε μία δέσμη ενεÏγειών"
@@ -5742,6 +5756,23 @@ msgstr "Μάσκα εκπομπής"
#: editor/plugins/cpu_particles_2d_editor_plugin.cpp
#: editor/plugins/particles_2d_editor_plugin.cpp
+#, fuzzy
+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
+#, fuzzy
+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 "ΚαταγÏαφή από εικονοστοιχείο"
@@ -9504,6 +9535,10 @@ msgid "Export PCK/Zip"
msgstr "Εξαγωγή PCK/ZIP"
#: editor/project_export.cpp
+msgid "Export Project"
+msgstr "Εξαγωγή έÏγου"
+
+#: editor/project_export.cpp
msgid "Export mode?"
msgstr "ΛειτουÏγία εξαγωγής;"
@@ -9597,10 +9632,6 @@ msgid "Couldn't create project.godot in project path."
msgstr "Δεν ήταν δυνατή η δημιουÏγία του project.godot στη διαδÏομή έÏγου."
#: editor/project_manager.cpp
-msgid "The following files failed extraction from package:"
-msgstr "Η εξαγωγή των ακόλουθων αÏχείων από το πακέτο απέτυχε:"
-
-#: editor/project_manager.cpp
msgid "Rename Project"
msgstr "Μετονομασία έÏγου"
@@ -10044,9 +10075,8 @@ msgid "Settings saved OK."
msgstr "Οι Ïυθμίσεις αποθηκεÏτικαν εντάξει."
#: editor/project_settings_editor.cpp
-#, fuzzy
msgid "Moved Input Action Event"
-msgstr "ΠÏοσθήκη συμβάντος εισόδου"
+msgstr "Μετακινήθηκε συμβάν εισόδου"
#: editor/project_settings_editor.cpp
msgid "Override for Feature"
@@ -10413,9 +10443,8 @@ msgid "Instance Scene(s)"
msgstr "ΔημιουÏγία στιγμιοτÏπυ σκηνών"
#: editor/scene_tree_dock.cpp
-#, fuzzy
msgid "Replace with Branch Scene"
-msgstr "Αποθήκευσι ÎºÎ»Î±Î´Î¹Î¿Ï Ï‰Ï‚ σκηνή"
+msgstr "Αποθήκευση ÎºÎ»Î±Î´Î¹Î¿Ï Ï‰Ï‚ σκηνή"
#: editor/scene_tree_dock.cpp
msgid "Instance Child Scene"
@@ -10461,23 +10490,20 @@ msgid "Make node as Root"
msgstr "Κάνε κόμβο Ïίζα"
#: editor/scene_tree_dock.cpp
-#, fuzzy
msgid "Delete %d nodes?"
-msgstr "ΔιαγÏαφή Κόμβων"
+msgstr "ΔιαγÏαφή %d κόμβων;"
#: editor/scene_tree_dock.cpp
-#, fuzzy
msgid "Delete the root node \"%s\"?"
-msgstr "ΔιαγÏαφή κόμβων γÏαφήματος"
+msgstr "ΔιαγÏαφή κόμβου Ïίζας \"%s\";"
#: editor/scene_tree_dock.cpp
msgid "Delete node \"%s\" and its children?"
msgstr "ΔιαγÏαφή κόμβου \"%s\" και των παιδιών του;"
#: editor/scene_tree_dock.cpp
-#, fuzzy
msgid "Delete node \"%s\"?"
-msgstr "ΔιαγÏαφή Κόμβων"
+msgstr "ΔιαγÏαφή κόμβων \"%s\";"
#: editor/scene_tree_dock.cpp
msgid "Can not perform with the root node."
@@ -10855,6 +10881,11 @@ msgstr "Θα φοÏτώσει υπαÏκτό αÏχείο δέσμης ενεÏÎ
#: editor/script_create_dialog.cpp
#, fuzzy
+msgid "Script file already exists."
+msgstr "Η ενέÏγεια '%s' υπάÏχει ήδη!"
+
+#: editor/script_create_dialog.cpp
+#, fuzzy
msgid "Class Name:"
msgstr "Όνομα κλάσης"
@@ -12606,7 +12637,15 @@ msgstr ""
"Αυτός ο κόμβος έχει καταÏγηθεί. ΧÏησιμοποιήστε το AnimationTree αντ 'αυτοÏ."
#: scene/gui/color_picker.cpp
-msgid "Pick a color from the screen."
+msgid ""
+"Color: #%s\n"
+"LMB: Set color\n"
+"RMB: Remove preset"
+msgstr ""
+
+#: scene/gui/color_picker.cpp
+#, fuzzy
+msgid "Pick a color from the editor window."
msgstr "Διαλέξτε ένα χÏώμα από την οθόνη."
#: scene/gui/color_picker.cpp
@@ -12734,6 +12773,12 @@ msgstr ""
msgid "Constants cannot be modified."
msgstr "Οι σταθεÏές δεν μποÏοÏν να Ï„ÏοποποιηθοÏν."
+#~ msgid "Project export failed with error code %d."
+#~ msgstr "Η εξαγωγή του έÏγου απέτυχε με κωδικό %d."
+
+#~ msgid "Password:"
+#~ msgstr "Κωδικός:"
+
#~ msgid "Identifier segments must be of non-zero length."
#~ msgstr "Τα τμήματα του αναγνωÏÎ¹ÏƒÏ„Î¹ÎºÎ¿Ï Ï€Ïέπει να έχουν μη μηδενικό μήκος."
@@ -13205,9 +13250,6 @@ msgstr "Οι σταθεÏές δεν μποÏοÏν να Ï„ÏοποποιηθοÏ
#~ msgid "Create folder"
#~ msgstr "ΔημιουÏγία φακέλου"
-#~ msgid "Already existing"
-#~ msgstr "ΥπάÏχει ήδη"
-
#, fuzzy
#~ msgid "Custom Node"
#~ msgstr "Αποκοπή κόμβων"
@@ -13256,10 +13298,6 @@ msgstr "Οι σταθεÏές δεν μποÏοÏν να Ï„ÏοποποιηθοÏ
#~ msgstr "Το PathFollow2D δουλεÏει μόνο όταν κληÏονομεί έναν κόμβο Path2D."
#, fuzzy
-#~ msgid "Split already exists."
-#~ msgstr "Η ενέÏγεια '%s' υπάÏχει ήδη!"
-
-#, fuzzy
#~ msgid "Add Split"
#~ msgstr "ΠÏοσθήκη σημείου"
diff --git a/editor/translations/eo.po b/editor/translations/eo.po
index 6639860c31..152834ff55 100644
--- a/editor/translations/eo.po
+++ b/editor/translations/eo.po
@@ -1186,10 +1186,22 @@ msgid "Error opening package file, not in ZIP format."
msgstr ""
#: editor/editor_asset_installer.cpp
+msgid "%s (Already Exists)"
+msgstr ""
+
+#: editor/editor_asset_installer.cpp
msgid "Uncompressing Assets"
msgstr ""
#: editor/editor_asset_installer.cpp editor/project_manager.cpp
+msgid "The following files failed extraction from package:"
+msgstr ""
+
+#: editor/editor_asset_installer.cpp
+msgid "And %s more files."
+msgstr ""
+
+#: editor/editor_asset_installer.cpp editor/project_manager.cpp
msgid "Package installed successfully!"
msgstr ""
@@ -1198,6 +1210,10 @@ msgstr ""
msgid "Success!"
msgstr "Sukcesis!"
+#: editor/editor_asset_installer.cpp
+msgid "Package Contents:"
+msgstr ""
+
#: editor/editor_asset_installer.cpp editor/editor_node.cpp
msgid "Install"
msgstr ""
@@ -1336,6 +1352,11 @@ msgid "Invalid file, not an audio bus layout."
msgstr ""
#: editor/editor_audio_buses.cpp
+#, fuzzy
+msgid "Error saving file: %s"
+msgstr "Eraro dum Åargante tiparon."
+
+#: editor/editor_audio_buses.cpp
msgid "Add Bus"
msgstr ""
@@ -2129,10 +2150,6 @@ msgid "New Window"
msgstr ""
#: editor/editor_node.cpp
-msgid "Project export failed with error code %d."
-msgstr ""
-
-#: editor/editor_node.cpp
msgid "Imported resources can't be saved."
msgstr ""
@@ -3004,10 +3021,6 @@ msgstr ""
msgid "Template Package"
msgstr "Åœablonoj"
-#: editor/editor_node.cpp editor/project_export.cpp
-msgid "Export Project"
-msgstr ""
-
#: editor/editor_node.cpp
msgid "Export Library"
msgstr ""
@@ -3017,10 +3030,6 @@ msgid "Merge With Existing"
msgstr ""
#: editor/editor_node.cpp
-msgid "Password:"
-msgstr ""
-
-#: editor/editor_node.cpp
msgid "Open & Run a Script"
msgstr "Malfermi & ruli skripto"
@@ -5601,6 +5610,22 @@ 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
+#, fuzzy
+msgid "Directed Border Pixels"
+msgstr "Dosierujoj kaj dosieroj:"
+
+#: editor/plugins/cpu_particles_2d_editor_plugin.cpp
+#: editor/plugins/particles_2d_editor_plugin.cpp
msgid "Capture from Pixel"
msgstr ""
@@ -9232,6 +9257,10 @@ msgid "Export PCK/Zip"
msgstr ""
#: editor/project_export.cpp
+msgid "Export Project"
+msgstr ""
+
+#: editor/project_export.cpp
msgid "Export mode?"
msgstr ""
@@ -9322,10 +9351,6 @@ msgid "Couldn't create project.godot in project path."
msgstr ""
#: editor/project_manager.cpp
-msgid "The following files failed extraction from package:"
-msgstr ""
-
-#: editor/project_manager.cpp
msgid "Rename Project"
msgstr "Renomi projekton"
@@ -10502,6 +10527,11 @@ msgstr ""
#: editor/script_create_dialog.cpp
#, fuzzy
+msgid "Script file already exists."
+msgstr "Grupa nomo jam ekzistas."
+
+#: editor/script_create_dialog.cpp
+#, fuzzy
msgid "Class Name:"
msgstr "Nomo:"
@@ -12044,7 +12074,14 @@ msgid "This node has been deprecated. Use AnimationTree instead."
msgstr ""
#: scene/gui/color_picker.cpp
-msgid "Pick a color from the screen."
+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
@@ -12159,8 +12196,5 @@ msgstr ""
#~ msgid "Unknown font format."
#~ msgstr "Nekonata tipara formo."
-#~ msgid "Error loading font."
-#~ msgstr "Eraro dum Åargante tiparon."
-
#~ msgid "Invalid font size."
#~ msgstr "Nevalida tipara grando."
diff --git a/editor/translations/es.po b/editor/translations/es.po
index d3142558f2..400178ff7c 100644
--- a/editor/translations/es.po
+++ b/editor/translations/es.po
@@ -14,7 +14,7 @@
# Diego López <diegodario21@gmail.com>, 2017.
# eon-s <emanuel.segretin@gmail.com>, 2018, 2019.
# Gustavo Leon <gleondiaz@gmail.com>, 2017-2018.
-# Javier Ocampos <xavier.ocampos@gmail.com>, 2018, 2019.
+# Javier Ocampos <xavier.ocampos@gmail.com>, 2018, 2019, 2020.
# Jose Maria Martinez <josemar1992@hotmail.com>, 2018.
# Juan Quiroga <juanquiroga9@gmail.com>, 2017.
# Kiji Pixel <raccoon.fella@gmail.com>, 2017.
@@ -46,7 +46,7 @@ msgid ""
msgstr ""
"Project-Id-Version: Godot Engine editor\n"
"POT-Creation-Date: \n"
-"PO-Revision-Date: 2019-12-25 12:45+0000\n"
+"PO-Revision-Date: 2020-01-11 03:05+0000\n"
"Last-Translator: Javier Ocampos <xavier.ocampos@gmail.com>\n"
"Language-Team: Spanish <https://hosted.weblate.org/projects/godot-engine/"
"godot/es/>\n"
@@ -55,7 +55,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 3.10\n"
+"X-Generator: Weblate 3.10.1\n"
#: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp
#: modules/visual_script/visual_script_builtin_funcs.cpp
@@ -140,7 +140,7 @@ msgstr "Balanceado"
#: editor/animation_bezier_editor.cpp
msgid "Mirror"
-msgstr "Espejo"
+msgstr "Mirror"
#: editor/animation_bezier_editor.cpp editor/editor_profiler.cpp
msgid "Time:"
@@ -459,7 +459,7 @@ msgstr "No es posible agregar una nueva pista sin una raíz"
#: editor/animation_track_editor.cpp
msgid "Invalid track for Bezier (no suitable sub-properties)"
-msgstr ""
+msgstr "Pista inválida para Bezier (no hay sub-propiedades adecuadas)"
#: editor/animation_track_editor.cpp
msgid "Add Bezier Track"
@@ -637,7 +637,7 @@ msgstr "Usar Curvas Bezier"
#: editor/animation_track_editor.cpp
msgid "Anim. Optimizer"
-msgstr "Optimizador de Animación"
+msgstr "Optimizar Animación"
#: editor/animation_track_editor.cpp
msgid "Max. Linear Error:"
@@ -1236,10 +1236,24 @@ msgid "Error opening package file, not in ZIP format."
msgstr "Error al abrir el archivo comprimido, no está en formato ZIP."
#: editor/editor_asset_installer.cpp
+#, fuzzy
+msgid "%s (Already Exists)"
+msgstr "Ya existe"
+
+#: editor/editor_asset_installer.cpp
msgid "Uncompressing Assets"
msgstr "Descomprimiendo Assets"
#: editor/editor_asset_installer.cpp editor/project_manager.cpp
+msgid "The following files failed extraction from package:"
+msgstr "Los siguientes archivos no se pudieron extraer del paquete:"
+
+#: editor/editor_asset_installer.cpp
+#, fuzzy
+msgid "And %s more files."
+msgstr "%d más archivos"
+
+#: editor/editor_asset_installer.cpp editor/project_manager.cpp
msgid "Package installed successfully!"
msgstr "¡Paquete instalado con éxito!"
@@ -1248,6 +1262,11 @@ msgstr "¡Paquete instalado con éxito!"
msgid "Success!"
msgstr "¡Éxito!"
+#: editor/editor_asset_installer.cpp
+#, fuzzy
+msgid "Package Contents:"
+msgstr "Contenido:"
+
#: editor/editor_asset_installer.cpp editor/editor_node.cpp
msgid "Install"
msgstr "Instalar"
@@ -1386,6 +1405,11 @@ msgid "Invalid file, not an audio bus layout."
msgstr "Archivo inválido. No es un layout de bus de audio."
#: editor/editor_audio_buses.cpp
+#, fuzzy
+msgid "Error saving file: %s"
+msgstr "¡Error guardando archivo!"
+
+#: editor/editor_audio_buses.cpp
msgid "Add Bus"
msgstr "Añadir Bus"
@@ -1607,7 +1631,7 @@ msgstr ""
#: 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 "Plantilla debug personalizada no encontrada."
+msgstr "No se encontró la plantilla de depuración personalizada."
#: editor/editor_export.cpp platform/android/export/export.cpp
#: platform/iphone/export/export.cpp platform/javascript/export/export.cpp
@@ -2044,9 +2068,8 @@ msgid "Case Sensitive"
msgstr "Respetar mayús/minúsculas"
#: editor/editor_help_search.cpp
-#, fuzzy
msgid "Show Hierarchy"
-msgstr "Mostrar Ayudantes"
+msgstr "Mostrar Jerarquía"
#: editor/editor_help_search.cpp
msgid "Display All"
@@ -2085,9 +2108,8 @@ msgid "Class"
msgstr "Clase"
#: editor/editor_help_search.cpp
-#, fuzzy
msgid "Method"
-msgstr "Métodos"
+msgstr "Método"
#: editor/editor_help_search.cpp editor/plugins/script_text_editor.cpp
msgid "Signal"
@@ -2098,12 +2120,10 @@ msgid "Constant"
msgstr "Constante"
#: editor/editor_help_search.cpp
-#, fuzzy
msgid "Property"
-msgstr "Propiedad:"
+msgstr "Propiedad"
#: editor/editor_help_search.cpp
-#, fuzzy
msgid "Theme Property"
msgstr "Propiedades del Tema"
@@ -2188,10 +2208,6 @@ msgid "New Window"
msgstr "Nueva Ventana"
#: editor/editor_node.cpp
-msgid "Project export failed with error code %d."
-msgstr "La exportación del proyecto falló con el código de error %d."
-
-#: editor/editor_node.cpp
msgid "Imported resources can't be saved."
msgstr "Los recursos importados no se pueden guardar."
@@ -3118,10 +3134,6 @@ msgstr "Importar plantillas desde un archivo ZIP"
msgid "Template Package"
msgstr "Paquete de Plantillas"
-#: editor/editor_node.cpp editor/project_export.cpp
-msgid "Export Project"
-msgstr "Exportar Proyecto"
-
#: editor/editor_node.cpp
msgid "Export Library"
msgstr "Exportar Librería"
@@ -3131,10 +3143,6 @@ msgid "Merge With Existing"
msgstr "Combinar Con Existentes"
#: editor/editor_node.cpp
-msgid "Password:"
-msgstr "Contraseña:"
-
-#: editor/editor_node.cpp
msgid "Open & Run a Script"
msgstr "Abrir y Ejecutar un Script"
@@ -3500,13 +3508,14 @@ msgid "Importing:"
msgstr "Importando:"
#: editor/export_template_manager.cpp
-#, fuzzy
msgid "Error getting the list of mirrors."
-msgstr "¡Error al escribir el PCK de proyecto!"
+msgstr "Error al obtener la lista de mirrors."
#: editor/export_template_manager.cpp
msgid "Error parsing JSON of mirror list. Please report this issue!"
msgstr ""
+"Error al analizar el JSON de la lista de mirrors. ¡Por favor, informa de "
+"este problema!"
#: editor/export_template_manager.cpp
msgid ""
@@ -4697,9 +4706,8 @@ msgid "Move Node"
msgstr "Mover Nodo"
#: editor/plugins/animation_state_machine_editor.cpp
-#, fuzzy
msgid "Transition exists!"
-msgstr "Transiciones"
+msgstr "¡La transición existe!"
#: editor/plugins/animation_state_machine_editor.cpp
msgid "Add Transition"
@@ -5307,31 +5315,31 @@ msgstr "Centro"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Left Wide"
-msgstr "Izquierda Ancha"
+msgstr "Ancho Izquierda"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Top Wide"
-msgstr "Superior Ancha"
+msgstr "Ancho Superior"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Right Wide"
-msgstr "Derecha Ancha"
+msgstr "Ancho Derecha"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Bottom Wide"
-msgstr "Inferior Ancha"
+msgstr "Ancho Inferior"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "VCenter Wide"
-msgstr "Centro Vert. Ancha"
+msgstr "Ancho Centro Vert."
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "HCenter Wide"
-msgstr "Centro Horiz. Ancha"
+msgstr "Ancho Centro Horiz."
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Full Rect"
-msgstr "Completa"
+msgstr "Completo"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Keep Ratio"
@@ -5740,7 +5748,7 @@ msgstr "Editar Polígono (Eliminar Punto)"
#: editor/plugins/collision_shape_2d_editor_plugin.cpp
msgid "Set Handle"
-msgstr "Establecer Handle"
+msgstr "Establecer Manipulador"
#: editor/plugins/cpu_particles_2d_editor_plugin.cpp
#: editor/plugins/particles_2d_editor_plugin.cpp
@@ -5777,6 +5785,23 @@ msgstr "Máscara de Emisión"
#: editor/plugins/cpu_particles_2d_editor_plugin.cpp
#: editor/plugins/particles_2d_editor_plugin.cpp
+#, fuzzy
+msgid "Solid Pixels"
+msgstr "Encoger (Píxeles): "
+
+#: 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
+#, fuzzy
+msgid "Directed Border Pixels"
+msgstr "Directorios y Archivos:"
+
+#: editor/plugins/cpu_particles_2d_editor_plugin.cpp
+#: editor/plugins/particles_2d_editor_plugin.cpp
msgid "Capture from Pixel"
msgstr "Capturar desde píxel"
@@ -5897,7 +5922,7 @@ msgstr "¡El Mesh está vacío!"
#: editor/plugins/mesh_instance_editor_plugin.cpp
msgid "Create Static Trimesh Body"
-msgstr "Crear Static Trimesh Body"
+msgstr "Crear StaticBody Triangular"
#: editor/plugins/mesh_instance_editor_plugin.cpp
msgid "Create Static Convex Body"
@@ -5909,7 +5934,7 @@ msgstr "¡No puedes hacer esto en una escena raíz!"
#: editor/plugins/mesh_instance_editor_plugin.cpp
msgid "Create Trimesh Static Shape"
-msgstr "Crear Forma Estática de Trimesh"
+msgstr "Crear Shape Estático Triangular"
#: editor/plugins/mesh_instance_editor_plugin.cpp
msgid "Failed creating shapes!"
@@ -5966,15 +5991,15 @@ msgstr "Mesh"
#: editor/plugins/mesh_instance_editor_plugin.cpp
msgid "Create Trimesh Static Body"
-msgstr "Crear Trimesh Static Body"
+msgstr "Crear StaticBody Triangular"
#: editor/plugins/mesh_instance_editor_plugin.cpp
msgid "Create Trimesh Collision Sibling"
-msgstr "Crear Trimesh Collision Hermano"
+msgstr "Crear Collider Triangular Hermano"
#: editor/plugins/mesh_instance_editor_plugin.cpp
msgid "Create Convex Collision Sibling(s)"
-msgstr "Crear Convex Collision Hermano(s)"
+msgstr "Crear Collider Convexo Hermano(s)"
#: editor/plugins/mesh_instance_editor_plugin.cpp
msgid "Create Outline Mesh..."
@@ -6002,18 +6027,19 @@ msgstr "Tamaño del Outline:"
#: editor/plugins/mesh_instance_editor_plugin.cpp
msgid "UV Channel Debug"
-msgstr ""
+msgstr "Depuración del Canal UV"
#: editor/plugins/mesh_library_editor_plugin.cpp
msgid "Remove item %d?"
msgstr "¿Quieres borrar el elemento %d?"
#: editor/plugins/mesh_library_editor_plugin.cpp
-#, fuzzy
msgid ""
"Update from existing scene?:\n"
"%s"
-msgstr "Actualizar desde escena"
+msgstr ""
+"¿Actualizar desde la escena existente?\n"
+"%s"
#: editor/plugins/mesh_library_editor_plugin.cpp
msgid "Mesh Library"
@@ -6302,12 +6328,12 @@ msgstr "Opciones"
#: editor/plugins/path_2d_editor_plugin.cpp
#: editor/plugins/path_editor_plugin.cpp
msgid "Mirror Handle Angles"
-msgstr "Manejadores de Ãngulos de Espejo"
+msgstr "Manipulador de Ãngulos de Espejo"
#: editor/plugins/path_2d_editor_plugin.cpp
#: editor/plugins/path_editor_plugin.cpp
msgid "Mirror Handle Lengths"
-msgstr "Manejadores de Tamaño de Espejo"
+msgstr "Manipulador de Tamaño de Espejo"
#: editor/plugins/path_editor_plugin.cpp
msgid "Curve Point #"
@@ -7566,9 +7592,8 @@ msgid "Create Mesh2D"
msgstr "Crear Mesh2D"
#: editor/plugins/sprite_editor_plugin.cpp
-#, fuzzy
msgid "Mesh2D Preview"
-msgstr "Creando Vistas Previas de Mesh/es"
+msgstr "Vista Previa de Mesh2D"
#: editor/plugins/sprite_editor_plugin.cpp
msgid "Create Polygon2D"
@@ -7576,25 +7601,23 @@ msgstr "Crear Polygon2D"
#: editor/plugins/sprite_editor_plugin.cpp
msgid "Polygon2D Preview"
-msgstr ""
+msgstr "Vista Previa de Polygon2D"
#: editor/plugins/sprite_editor_plugin.cpp
msgid "Create CollisionPolygon2D"
msgstr "Crear CollisionPolygon2D"
#: editor/plugins/sprite_editor_plugin.cpp
-#, fuzzy
msgid "CollisionPolygon2D Preview"
-msgstr "Crear CollisionPolygon2D"
+msgstr "Vista Previa de CollisionPolygon2D"
#: editor/plugins/sprite_editor_plugin.cpp
msgid "Create LightOccluder2D"
msgstr "Crear LightOccluder2D"
#: editor/plugins/sprite_editor_plugin.cpp
-#, fuzzy
msgid "LightOccluder2D Preview"
-msgstr "Crear LightOccluder2D"
+msgstr "Vista Previa de LightOccluder2D"
#: editor/plugins/sprite_editor_plugin.cpp
msgid "Sprite is empty!"
@@ -7673,9 +7696,8 @@ msgid "Add Frame"
msgstr "Añadir Frame"
#: editor/plugins/sprite_frames_editor_plugin.cpp
-#, fuzzy
msgid "Unable to load images"
-msgstr "No se pudo cargar la imagen:"
+msgstr "No se pueden cargar las imágenes"
#: editor/plugins/sprite_frames_editor_plugin.cpp
msgid "ERROR: Couldn't load frame resource!"
@@ -8364,14 +8386,12 @@ msgid "Edit Tile Z Index"
msgstr "Editar Ãndice Z de Tile"
#: editor/plugins/tile_set_editor_plugin.cpp
-#, fuzzy
msgid "Make Convex"
-msgstr "Crear Póligono Convexo"
+msgstr "Crear Convexo"
#: editor/plugins/tile_set_editor_plugin.cpp
-#, fuzzy
msgid "Make Concave"
-msgstr "Crear Polígono Cóncavo"
+msgstr "Crear Cóncavo"
#: editor/plugins/tile_set_editor_plugin.cpp
msgid "Create Collision Polygon"
@@ -9532,6 +9552,10 @@ msgid "Export PCK/Zip"
msgstr "Exportar PCK/Zip"
#: editor/project_export.cpp
+msgid "Export Project"
+msgstr "Exportar Proyecto"
+
+#: editor/project_export.cpp
msgid "Export mode?"
msgstr "¿Modo de Exportación?"
@@ -9557,7 +9581,7 @@ msgstr "Administrar Plantillas de Exportación"
#: editor/project_export.cpp
msgid "Export With Debug"
-msgstr "Exportar con depuración"
+msgstr "Exportar Con Depuración"
#: editor/project_manager.cpp
msgid "The path does not exist."
@@ -9625,10 +9649,6 @@ msgid "Couldn't create project.godot in project path."
msgstr "No se pudo crear project.godot en la ruta del proyecto."
#: editor/project_manager.cpp
-msgid "The following files failed extraction from package:"
-msgstr "Los siguientes archivos no se pudieron extraer del paquete:"
-
-#: editor/project_manager.cpp
msgid "Rename Project"
msgstr "Renombrar Proyecto"
@@ -10869,6 +10889,11 @@ msgid "Will load an existing script file."
msgstr "Se cargará un archivo de script existente."
#: editor/script_create_dialog.cpp
+#, fuzzy
+msgid "Script file already exists."
+msgstr "La división ya existe."
+
+#: editor/script_create_dialog.cpp
msgid "Class Name:"
msgstr "Nombre de Clase:"
@@ -11321,9 +11346,8 @@ msgid "Cursor Clear Rotation"
msgstr "Eliminar Rotación del Cursor"
#: modules/gridmap/grid_map_editor_plugin.cpp
-#, fuzzy
msgid "Paste Selects"
-msgstr "Borrar Selección"
+msgstr "Pegar Seleccionados"
#: modules/gridmap/grid_map_editor_plugin.cpp
msgid "Clear Selection"
@@ -11877,7 +11901,7 @@ msgstr "OpenJDK jarsigner no configurado en Configuración del Editor."
#: platform/android/export/export.cpp
msgid "Debug keystore not configured in the Editor Settings nor in the preset."
msgstr ""
-"Keystore debug no configurada en Configuración del Editor ni en el preset."
+"Debug keystore no configurada en Configuración del Editor ni en el preset."
#: platform/android/export/export.cpp
msgid "Custom build requires a valid Android SDK path in Editor Settings."
@@ -12565,7 +12589,15 @@ msgid "This node has been deprecated. Use AnimationTree instead."
msgstr "Este nodo ha quedado obsoleto. Usa AnimationTree en su lugar."
#: scene/gui/color_picker.cpp
-msgid "Pick a color from the screen."
+msgid ""
+"Color: #%s\n"
+"LMB: Set color\n"
+"RMB: Remove preset"
+msgstr ""
+
+#: scene/gui/color_picker.cpp
+#, fuzzy
+msgid "Pick a color from the editor window."
msgstr "Selecciona un color de la pantalla."
#: scene/gui/color_picker.cpp
@@ -12689,6 +12721,12 @@ msgstr "Solo se pueden asignar variaciones en funciones de vértice."
msgid "Constants cannot be modified."
msgstr "Las constantes no pueden modificarse."
+#~ msgid "Project export failed with error code %d."
+#~ msgstr "La exportación del proyecto falló con el código de error %d."
+
+#~ msgid "Password:"
+#~ msgstr "Contraseña:"
+
#~ msgid "Identifier segments must be of non-zero length."
#~ msgstr "Los segmentos de un identificador deben ser de largo no nulo."
@@ -13175,9 +13213,6 @@ msgstr "Las constantes no pueden modificarse."
#~ msgid "Create folder"
#~ msgstr "Crear carpeta"
-#~ msgid "Already existing"
-#~ msgstr "Ya existe"
-
#~ msgid "Custom Node"
#~ msgstr "Nodo personalizado"
@@ -13229,9 +13264,6 @@ msgstr "Las constantes no pueden modificarse."
#~ msgid "Split can't form an existing edge."
#~ msgstr "La división no puede formar un borde existente."
-#~ msgid "Split already exists."
-#~ msgstr "La división ya existe."
-
#~ msgid "Add Split"
#~ msgstr "Agregar división"
diff --git a/editor/translations/es_AR.po b/editor/translations/es_AR.po
index d1ec00bf87..2109b2bfdb 100644
--- a/editor/translations/es_AR.po
+++ b/editor/translations/es_AR.po
@@ -3,12 +3,12 @@
# Copyright (c) 2014-2020 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.
+# Lisandro Lorea <lisandrolorea@gmail.com>, 2016-2018, 2019, 2020.
# Roger Blanco Ribera <roger.blancoribera@gmail.com>, 2016-2018.
# Sebastian Silva <sebastian@sugarlabs.org>, 2016.
# Jose Luis Bossio <joseluisbossio@gmail.com>, 2018.
# Reynaldo Cruz <rcruz60@gmail.com>, 2018.
-# Javier Ocampos <xavier.ocampos@gmail.com>, 2018, 2019.
+# Javier Ocampos <xavier.ocampos@gmail.com>, 2018, 2019, 2020.
# Andrés S <andres.segovia.dev@gmail.com>, 2019.
# Florencia Menéndez <mariaflormz2@gmail.com>, 2019.
# roger <616steam@gmail.com>, 2019.
@@ -17,8 +17,8 @@ msgid ""
msgstr ""
"Project-Id-Version: Godot Engine editor\n"
"POT-Creation-Date: \n"
-"PO-Revision-Date: 2019-12-25 12:45+0000\n"
-"Last-Translator: Lisandro Lorea <lisandrolorea@gmail.com>\n"
+"PO-Revision-Date: 2020-01-11 03:05+0000\n"
+"Last-Translator: Javier Ocampos <xavier.ocampos@gmail.com>\n"
"Language-Team: Spanish (Argentina) <https://hosted.weblate.org/projects/"
"godot-engine/godot/es_AR/>\n"
"Language: es_AR\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 3.10\n"
+"X-Generator: Weblate 3.10.1\n"
#: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp
#: modules/visual_script/visual_script_builtin_funcs.cpp
@@ -430,7 +430,7 @@ msgstr "No es posible agregar una nueva pista sin una raíz"
#: editor/animation_track_editor.cpp
msgid "Invalid track for Bezier (no suitable sub-properties)"
-msgstr ""
+msgstr "Pista inválida para Bezier (no hay sub-propiedades adecuadas)"
#: editor/animation_track_editor.cpp
msgid "Add Bezier Track"
@@ -1205,10 +1205,24 @@ msgid "Error opening package file, not in ZIP format."
msgstr "Error al abrir el archivo comprimido, no está en formato ZIP."
#: editor/editor_asset_installer.cpp
+#, fuzzy
+msgid "%s (Already Exists)"
+msgstr "Ya existe"
+
+#: editor/editor_asset_installer.cpp
msgid "Uncompressing Assets"
msgstr "Descomprimiendo Assets"
#: editor/editor_asset_installer.cpp editor/project_manager.cpp
+msgid "The following files failed extraction from package:"
+msgstr "Los siguientes archivos no se pudieron extraer del paquete:"
+
+#: editor/editor_asset_installer.cpp
+#, fuzzy
+msgid "And %s more files."
+msgstr "%d más archivos"
+
+#: editor/editor_asset_installer.cpp editor/project_manager.cpp
msgid "Package installed successfully!"
msgstr "El Paquete se instaló exitosamente!"
@@ -1217,6 +1231,11 @@ msgstr "El Paquete se instaló exitosamente!"
msgid "Success!"
msgstr "¡Éxito!"
+#: editor/editor_asset_installer.cpp
+#, fuzzy
+msgid "Package Contents:"
+msgstr "Contenido:"
+
#: editor/editor_asset_installer.cpp editor/editor_node.cpp
msgid "Install"
msgstr "Instalar"
@@ -1355,6 +1374,11 @@ msgid "Invalid file, not an audio bus layout."
msgstr "Archivo inválido. No es un layout de bus de audio."
#: editor/editor_audio_buses.cpp
+#, fuzzy
+msgid "Error saving file: %s"
+msgstr "Error guardando archivo!"
+
+#: editor/editor_audio_buses.cpp
msgid "Add Bus"
msgstr "Agregar Bus"
@@ -2009,9 +2033,8 @@ msgid "Case Sensitive"
msgstr "Respetar Mayúsculas/Minúsculas"
#: editor/editor_help_search.cpp
-#, fuzzy
msgid "Show Hierarchy"
-msgstr "Mostrar Ayudantes"
+msgstr "Mostrar Jerarquía"
#: editor/editor_help_search.cpp
msgid "Display All"
@@ -2050,9 +2073,8 @@ msgid "Class"
msgstr "Clase"
#: editor/editor_help_search.cpp
-#, fuzzy
msgid "Method"
-msgstr "Métodos"
+msgstr "Método"
#: editor/editor_help_search.cpp editor/plugins/script_text_editor.cpp
msgid "Signal"
@@ -2063,14 +2085,12 @@ msgid "Constant"
msgstr "Constante"
#: editor/editor_help_search.cpp
-#, fuzzy
msgid "Property"
-msgstr "Propiedad:"
+msgstr "Propiedad"
#: editor/editor_help_search.cpp
-#, fuzzy
msgid "Theme Property"
-msgstr "Propiedades de Tema"
+msgstr "Propiedades del Tema"
#: editor/editor_inspector.cpp editor/project_settings_editor.cpp
msgid "Property:"
@@ -2153,10 +2173,6 @@ msgid "New Window"
msgstr "Nueva Ventana"
#: editor/editor_node.cpp
-msgid "Project export failed with error code %d."
-msgstr "La exportación del proyecto falló con el código de error %d."
-
-#: editor/editor_node.cpp
msgid "Imported resources can't be saved."
msgstr "Los recursos importados no se pueden guardar."
@@ -3084,10 +3100,6 @@ msgstr "Importar Plantillas Desde Archivo ZIP"
msgid "Template Package"
msgstr "Paquete de Plantillas"
-#: editor/editor_node.cpp editor/project_export.cpp
-msgid "Export Project"
-msgstr "Exportar Proyecto"
-
#: editor/editor_node.cpp
msgid "Export Library"
msgstr "Exportar Libreria"
@@ -3097,10 +3109,6 @@ msgid "Merge With Existing"
msgstr "Mergear Con Existentes"
#: editor/editor_node.cpp
-msgid "Password:"
-msgstr "Contraseña:"
-
-#: editor/editor_node.cpp
msgid "Open & Run a Script"
msgstr "Abrir y Correr un Script"
@@ -3465,13 +3473,14 @@ msgid "Importing:"
msgstr "Importando:"
#: editor/export_template_manager.cpp
-#, fuzzy
msgid "Error getting the list of mirrors."
-msgstr "Error al crear el objeto firma."
+msgstr "Error al obtener la lista de mirrors."
#: editor/export_template_manager.cpp
msgid "Error parsing JSON of mirror list. Please report this issue!"
msgstr ""
+"Error al parsear el JSON de la lista de mirrors. Por favor reportá este "
+"problema!"
#: editor/export_template_manager.cpp
msgid ""
@@ -4663,9 +4672,8 @@ msgid "Move Node"
msgstr "Mover Nodo"
#: editor/plugins/animation_state_machine_editor.cpp
-#, fuzzy
msgid "Transition exists!"
-msgstr "Transiciones"
+msgstr "¡La transición existe!"
#: editor/plugins/animation_state_machine_editor.cpp
msgid "Add Transition"
@@ -5742,6 +5750,23 @@ msgstr "Máscara de Emisión"
#: editor/plugins/cpu_particles_2d_editor_plugin.cpp
#: editor/plugins/particles_2d_editor_plugin.cpp
+#, fuzzy
+msgid "Solid Pixels"
+msgstr "Achicar (Pixeles): "
+
+#: 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
+#, fuzzy
+msgid "Directed Border Pixels"
+msgstr "Directorios y Archivos:"
+
+#: editor/plugins/cpu_particles_2d_editor_plugin.cpp
+#: editor/plugins/particles_2d_editor_plugin.cpp
msgid "Capture from Pixel"
msgstr "Capturar desde Pixel"
@@ -5931,15 +5956,15 @@ msgstr "Mesh"
#: editor/plugins/mesh_instance_editor_plugin.cpp
msgid "Create Trimesh Static Body"
-msgstr "Crear Body Estático Trimesh"
+msgstr "Crear StaticBody Triangular"
#: editor/plugins/mesh_instance_editor_plugin.cpp
msgid "Create Trimesh Collision Sibling"
-msgstr "Crear Trimesh Collision Sibling"
+msgstr "Crear Collider Triangular Hermano"
#: editor/plugins/mesh_instance_editor_plugin.cpp
msgid "Create Convex Collision Sibling(s)"
-msgstr "Crear Convex Collision Hemano(s)"
+msgstr "Crear Collider Convexo Hermano(s)"
#: editor/plugins/mesh_instance_editor_plugin.cpp
msgid "Create Outline Mesh..."
@@ -5967,18 +5992,19 @@ msgstr "Tamaño de Outline:"
#: editor/plugins/mesh_instance_editor_plugin.cpp
msgid "UV Channel Debug"
-msgstr ""
+msgstr "Depuración de Canal UV"
#: editor/plugins/mesh_library_editor_plugin.cpp
msgid "Remove item %d?"
msgstr "Remover item %d?"
#: editor/plugins/mesh_library_editor_plugin.cpp
-#, fuzzy
msgid ""
"Update from existing scene?:\n"
"%s"
-msgstr "Acutalizar desde Escena"
+msgstr ""
+"¿Actualizar desde escena existente?\n"
+"%s"
#: editor/plugins/mesh_library_editor_plugin.cpp
msgid "Mesh Library"
@@ -7531,9 +7557,8 @@ msgid "Create Mesh2D"
msgstr "Crear Mesh2D"
#: editor/plugins/sprite_editor_plugin.cpp
-#, fuzzy
msgid "Mesh2D Preview"
-msgstr "Creando Vistas Previas de Mesh/es"
+msgstr "Vista Previa de Mesh2D"
#: editor/plugins/sprite_editor_plugin.cpp
msgid "Create Polygon2D"
@@ -7541,25 +7566,23 @@ msgstr "Crear Polygon2D"
#: editor/plugins/sprite_editor_plugin.cpp
msgid "Polygon2D Preview"
-msgstr ""
+msgstr "Vista Previa de Polygon2D"
#: editor/plugins/sprite_editor_plugin.cpp
msgid "Create CollisionPolygon2D"
msgstr "Crear CollisionPolygon2D"
#: editor/plugins/sprite_editor_plugin.cpp
-#, fuzzy
msgid "CollisionPolygon2D Preview"
-msgstr "Crear CollisionPolygon2D"
+msgstr "Vista Previa de CollisionPolygon2D"
#: editor/plugins/sprite_editor_plugin.cpp
msgid "Create LightOccluder2D"
msgstr "Crear LightOccluder2D"
#: editor/plugins/sprite_editor_plugin.cpp
-#, fuzzy
msgid "LightOccluder2D Preview"
-msgstr "Crear LightOccluder2D"
+msgstr "Vista Previa de LightOccluder2D"
#: editor/plugins/sprite_editor_plugin.cpp
msgid "Sprite is empty!"
@@ -7638,9 +7661,8 @@ msgid "Add Frame"
msgstr "Agregar Frame"
#: editor/plugins/sprite_frames_editor_plugin.cpp
-#, fuzzy
msgid "Unable to load images"
-msgstr "No se pudo cargar la imagen:"
+msgstr "No se pudieron cargar las imágenes"
#: editor/plugins/sprite_frames_editor_plugin.cpp
msgid "ERROR: Couldn't load frame resource!"
@@ -8328,14 +8350,12 @@ msgid "Edit Tile Z Index"
msgstr "Editar Z Index de Tile"
#: editor/plugins/tile_set_editor_plugin.cpp
-#, fuzzy
msgid "Make Convex"
-msgstr "Crear Polígono Convexo"
+msgstr "Hacer Convexo"
#: editor/plugins/tile_set_editor_plugin.cpp
-#, fuzzy
msgid "Make Concave"
-msgstr "Crear Polígono Cóncavo"
+msgstr "Hacer Cóncavo"
#: editor/plugins/tile_set_editor_plugin.cpp
msgid "Create Collision Polygon"
@@ -9496,6 +9516,10 @@ msgid "Export PCK/Zip"
msgstr "Exportar PCK/Zip"
#: editor/project_export.cpp
+msgid "Export Project"
+msgstr "Exportar Proyecto"
+
+#: editor/project_export.cpp
msgid "Export mode?"
msgstr "¿Modo de Exportación?"
@@ -9589,10 +9613,6 @@ msgid "Couldn't create project.godot in project path."
msgstr "No se pudo crear project.godot en la ruta de proyecto."
#: editor/project_manager.cpp
-msgid "The following files failed extraction from package:"
-msgstr "Los siguientes archivos no se pudieron extraer del paquete:"
-
-#: editor/project_manager.cpp
msgid "Rename Project"
msgstr "Renombrar Proyecto"
@@ -10835,6 +10855,11 @@ msgid "Will load an existing script file."
msgstr "Se cargará un archivo de script existente."
#: editor/script_create_dialog.cpp
+#, fuzzy
+msgid "Script file already exists."
+msgstr "La división ya existe."
+
+#: editor/script_create_dialog.cpp
msgid "Class Name:"
msgstr "Nombre de Clase:"
@@ -11286,9 +11311,8 @@ msgid "Cursor Clear Rotation"
msgstr "Restablecer Rotación en Cursor"
#: modules/gridmap/grid_map_editor_plugin.cpp
-#, fuzzy
msgid "Paste Selects"
-msgstr "Eliminar Selección"
+msgstr "Seleccionar al Pegar"
#: modules/gridmap/grid_map_editor_plugin.cpp
msgid "Clear Selection"
@@ -12524,7 +12548,15 @@ msgid "This node has been deprecated. Use AnimationTree instead."
msgstr "Este nodo ha sido deprecado. Usá AnimationTree."
#: scene/gui/color_picker.cpp
-msgid "Pick a color from the screen."
+msgid ""
+"Color: #%s\n"
+"LMB: Set color\n"
+"RMB: Remove preset"
+msgstr ""
+
+#: scene/gui/color_picker.cpp
+#, fuzzy
+msgid "Pick a color from the editor window."
msgstr "Elegir un color de la pantalla."
#: scene/gui/color_picker.cpp
@@ -12647,6 +12679,12 @@ msgstr "Solo se pueden asignar variaciones en funciones de vértice."
msgid "Constants cannot be modified."
msgstr "Las constantes no pueden modificarse."
+#~ msgid "Project export failed with error code %d."
+#~ msgstr "La exportación del proyecto falló con el código de error %d."
+
+#~ msgid "Password:"
+#~ msgstr "Contraseña:"
+
#~ msgid "Identifier segments must be of non-zero length."
#~ msgstr "Los segmentos de un identificador deben ser de largo no nulo."
@@ -12947,9 +12985,6 @@ msgstr "Las constantes no pueden modificarse."
#~ msgid "Create folder"
#~ msgstr "Crear carpeta"
-#~ msgid "Already existing"
-#~ msgstr "Ya existe"
-
#~ msgid "Custom Node"
#~ msgstr "Nodo Personalizado"
@@ -13001,9 +13036,6 @@ msgstr "Las constantes no pueden modificarse."
#~ msgid "Split can't form an existing edge."
#~ msgstr "La división no puede formar un borde existente."
-#~ msgid "Split already exists."
-#~ msgstr "La división ya existe."
-
#~ msgid "Add Split"
#~ msgstr "Agregar División"
diff --git a/editor/translations/et.po b/editor/translations/et.po
index 1ea5d3377a..656b354e9b 100644
--- a/editor/translations/et.po
+++ b/editor/translations/et.po
@@ -1158,10 +1158,22 @@ msgid "Error opening package file, not in ZIP format."
msgstr ""
#: editor/editor_asset_installer.cpp
+msgid "%s (Already Exists)"
+msgstr ""
+
+#: editor/editor_asset_installer.cpp
msgid "Uncompressing Assets"
msgstr ""
#: editor/editor_asset_installer.cpp editor/project_manager.cpp
+msgid "The following files failed extraction from package:"
+msgstr ""
+
+#: editor/editor_asset_installer.cpp
+msgid "And %s more files."
+msgstr ""
+
+#: editor/editor_asset_installer.cpp editor/project_manager.cpp
msgid "Package installed successfully!"
msgstr ""
@@ -1170,6 +1182,10 @@ msgstr ""
msgid "Success!"
msgstr ""
+#: editor/editor_asset_installer.cpp
+msgid "Package Contents:"
+msgstr ""
+
#: editor/editor_asset_installer.cpp editor/editor_node.cpp
msgid "Install"
msgstr ""
@@ -1308,6 +1324,10 @@ msgid "Invalid file, not an audio bus layout."
msgstr ""
#: editor/editor_audio_buses.cpp
+msgid "Error saving file: %s"
+msgstr ""
+
+#: editor/editor_audio_buses.cpp
msgid "Add Bus"
msgstr ""
@@ -2082,10 +2102,6 @@ msgid "New Window"
msgstr ""
#: editor/editor_node.cpp
-msgid "Project export failed with error code %d."
-msgstr ""
-
-#: editor/editor_node.cpp
msgid "Imported resources can't be saved."
msgstr ""
@@ -2925,10 +2941,6 @@ msgstr ""
msgid "Template Package"
msgstr ""
-#: editor/editor_node.cpp editor/project_export.cpp
-msgid "Export Project"
-msgstr ""
-
#: editor/editor_node.cpp
msgid "Export Library"
msgstr ""
@@ -2938,10 +2950,6 @@ msgid "Merge With Existing"
msgstr ""
#: editor/editor_node.cpp
-msgid "Password:"
-msgstr ""
-
-#: editor/editor_node.cpp
msgid "Open & Run a Script"
msgstr ""
@@ -5510,6 +5518,21 @@ 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 ""
@@ -9130,6 +9153,10 @@ msgid "Export PCK/Zip"
msgstr ""
#: editor/project_export.cpp
+msgid "Export Project"
+msgstr ""
+
+#: editor/project_export.cpp
msgid "Export mode?"
msgstr ""
@@ -9220,10 +9247,6 @@ msgid "Couldn't create project.godot in project path."
msgstr ""
#: editor/project_manager.cpp
-msgid "The following files failed extraction from package:"
-msgstr ""
-
-#: editor/project_manager.cpp
msgid "Rename Project"
msgstr ""
@@ -10384,6 +10407,10 @@ msgid "Will load an existing script file."
msgstr ""
#: editor/script_create_dialog.cpp
+msgid "Script file already exists."
+msgstr ""
+
+#: editor/script_create_dialog.cpp
msgid "Class Name:"
msgstr ""
@@ -11915,7 +11942,14 @@ msgid "This node has been deprecated. Use AnimationTree instead."
msgstr ""
#: scene/gui/color_picker.cpp
-msgid "Pick a color from the screen."
+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
diff --git a/editor/translations/eu.po b/editor/translations/eu.po
index e4897687be..4fe720ec38 100644
--- a/editor/translations/eu.po
+++ b/editor/translations/eu.po
@@ -1155,10 +1155,22 @@ msgid "Error opening package file, not in ZIP format."
msgstr ""
#: editor/editor_asset_installer.cpp
+msgid "%s (Already Exists)"
+msgstr ""
+
+#: editor/editor_asset_installer.cpp
msgid "Uncompressing Assets"
msgstr ""
#: editor/editor_asset_installer.cpp editor/project_manager.cpp
+msgid "The following files failed extraction from package:"
+msgstr ""
+
+#: editor/editor_asset_installer.cpp
+msgid "And %s more files."
+msgstr ""
+
+#: editor/editor_asset_installer.cpp editor/project_manager.cpp
msgid "Package installed successfully!"
msgstr ""
@@ -1167,6 +1179,10 @@ msgstr ""
msgid "Success!"
msgstr ""
+#: editor/editor_asset_installer.cpp
+msgid "Package Contents:"
+msgstr ""
+
#: editor/editor_asset_installer.cpp editor/editor_node.cpp
msgid "Install"
msgstr ""
@@ -1305,6 +1321,10 @@ msgid "Invalid file, not an audio bus layout."
msgstr ""
#: editor/editor_audio_buses.cpp
+msgid "Error saving file: %s"
+msgstr ""
+
+#: editor/editor_audio_buses.cpp
msgid "Add Bus"
msgstr ""
@@ -2077,10 +2097,6 @@ msgid "New Window"
msgstr ""
#: editor/editor_node.cpp
-msgid "Project export failed with error code %d."
-msgstr ""
-
-#: editor/editor_node.cpp
msgid "Imported resources can't be saved."
msgstr ""
@@ -2919,10 +2935,6 @@ msgstr ""
msgid "Template Package"
msgstr ""
-#: editor/editor_node.cpp editor/project_export.cpp
-msgid "Export Project"
-msgstr ""
-
#: editor/editor_node.cpp
msgid "Export Library"
msgstr ""
@@ -2932,10 +2944,6 @@ msgid "Merge With Existing"
msgstr ""
#: editor/editor_node.cpp
-msgid "Password:"
-msgstr ""
-
-#: editor/editor_node.cpp
msgid "Open & Run a Script"
msgstr ""
@@ -5497,6 +5505,21 @@ 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 ""
@@ -9113,6 +9136,10 @@ msgid "Export PCK/Zip"
msgstr ""
#: editor/project_export.cpp
+msgid "Export Project"
+msgstr ""
+
+#: editor/project_export.cpp
msgid "Export mode?"
msgstr ""
@@ -9203,10 +9230,6 @@ msgid "Couldn't create project.godot in project path."
msgstr ""
#: editor/project_manager.cpp
-msgid "The following files failed extraction from package:"
-msgstr ""
-
-#: editor/project_manager.cpp
msgid "Rename Project"
msgstr ""
@@ -10365,6 +10388,10 @@ msgid "Will load an existing script file."
msgstr ""
#: editor/script_create_dialog.cpp
+msgid "Script file already exists."
+msgstr ""
+
+#: editor/script_create_dialog.cpp
msgid "Class Name:"
msgstr ""
@@ -11890,7 +11917,14 @@ msgid "This node has been deprecated. Use AnimationTree instead."
msgstr ""
#: scene/gui/color_picker.cpp
-msgid "Pick a color from the screen."
+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
diff --git a/editor/translations/extract.py b/editor/translations/extract.py
index f75e01bb7b..e7ebda32df 100755
--- a/editor/translations/extract.py
+++ b/editor/translations/extract.py
@@ -23,13 +23,10 @@ if (not os.path.exists("editor")):
matches = []
for root, dirnames, filenames in os.walk('.'):
+ dirnames[:] = [d for d in dirnames if d not in ["thirdparty"]]
for filename in fnmatch.filter(filenames, '*.cpp'):
- if (filename.find("collada") != -1):
- continue
matches.append(os.path.join(root, filename))
for filename in fnmatch.filter(filenames, '*.h'):
- if (filename.find("collada") != -1):
- continue
matches.append(os.path.join(root, filename))
matches.sort()
diff --git a/editor/translations/fa.po b/editor/translations/fa.po
index 95e12e3d9e..b1effff53c 100644
--- a/editor/translations/fa.po
+++ b/editor/translations/fa.po
@@ -1232,10 +1232,24 @@ msgid "Error opening package file, not in ZIP format."
msgstr ""
#: editor/editor_asset_installer.cpp
+#, fuzzy
+msgid "%s (Already Exists)"
+msgstr "پیش از این وجود داشته است"
+
+#: editor/editor_asset_installer.cpp
msgid "Uncompressing Assets"
msgstr "عست های غیر Ùشرده"
#: editor/editor_asset_installer.cpp editor/project_manager.cpp
+msgid "The following files failed extraction from package:"
+msgstr ""
+
+#: editor/editor_asset_installer.cpp
+#, fuzzy
+msgid "And %s more files."
+msgstr "نمی‌تواند یک پوشه ایجاد شود."
+
+#: editor/editor_asset_installer.cpp editor/project_manager.cpp
msgid "Package installed successfully!"
msgstr ""
@@ -1244,6 +1258,11 @@ msgstr ""
msgid "Success!"
msgstr ""
+#: editor/editor_asset_installer.cpp
+#, fuzzy
+msgid "Package Contents:"
+msgstr "محتواها:"
+
#: editor/editor_asset_installer.cpp editor/editor_node.cpp
msgid "Install"
msgstr "نصب کردن"
@@ -1387,6 +1406,11 @@ msgid "Invalid file, not an audio bus layout."
msgstr ""
#: editor/editor_audio_buses.cpp
+#, fuzzy
+msgid "Error saving file: %s"
+msgstr "خطا در بارگذاری:"
+
+#: editor/editor_audio_buses.cpp
msgid "Add Bus"
msgstr ""
@@ -2219,10 +2243,6 @@ msgid "New Window"
msgstr ""
#: editor/editor_node.cpp
-msgid "Project export failed with error code %d."
-msgstr ""
-
-#: editor/editor_node.cpp
msgid "Imported resources can't be saved."
msgstr ""
@@ -3092,10 +3112,6 @@ msgstr "واردکردن قالب ها از درون یک Ùایل ZIP"
msgid "Template Package"
msgstr "قالب ها"
-#: editor/editor_node.cpp editor/project_export.cpp
-msgid "Export Project"
-msgstr "صدور پروژه"
-
#: editor/editor_node.cpp
msgid "Export Library"
msgstr "صدور کتابخانه"
@@ -3105,10 +3121,6 @@ msgid "Merge With Existing"
msgstr "ترکیب کردن با نمونه ی موجود"
#: editor/editor_node.cpp
-msgid "Password:"
-msgstr "گذرواژه:"
-
-#: editor/editor_node.cpp
msgid "Open & Run a Script"
msgstr "گشودن و اجرای یک اسکریپت"
@@ -5838,6 +5850,22 @@ 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
+#, fuzzy
+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 ""
@@ -9678,6 +9706,10 @@ msgid "Export PCK/Zip"
msgstr "صدور pck/zip"
#: editor/project_export.cpp
+msgid "Export Project"
+msgstr "صدور پروژه"
+
+#: editor/project_export.cpp
#, fuzzy
msgid "Export mode?"
msgstr "حالت صدور:"
@@ -9774,10 +9806,6 @@ msgid "Couldn't create project.godot in project path."
msgstr ""
#: editor/project_manager.cpp
-msgid "The following files failed extraction from package:"
-msgstr ""
-
-#: editor/project_manager.cpp
msgid "Rename Project"
msgstr "تغییر نام پروژه"
@@ -11007,6 +11035,11 @@ msgstr ""
#: editor/script_create_dialog.cpp
#, fuzzy
+msgid "Script file already exists."
+msgstr "پیش از این وجود داشته است"
+
+#: editor/script_create_dialog.cpp
+#, fuzzy
msgid "Class Name:"
msgstr "کلاس:"
@@ -12690,7 +12723,14 @@ msgid "This node has been deprecated. Use AnimationTree instead."
msgstr ""
#: scene/gui/color_picker.cpp
-msgid "Pick a color from the screen."
+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
@@ -12805,6 +12845,9 @@ msgstr ""
msgid "Constants cannot be modified."
msgstr ""
+#~ msgid "Password:"
+#~ msgstr "گذرواژه:"
+
#~ msgid "Shift+"
#~ msgstr "+Shift"
@@ -12953,9 +12996,6 @@ msgstr ""
#~ msgid "Create folder"
#~ msgstr "ساختن پوشه"
-#~ msgid "Already existing"
-#~ msgstr "پیش از این وجود داشته است"
-
#, fuzzy
#~ msgid "Custom Node"
#~ msgstr "ساختن گره"
@@ -12990,10 +13030,6 @@ msgstr ""
#~ "کار می‌کند."
#, fuzzy
-#~ msgid "Split already exists."
-#~ msgstr "پیش از این وجود داشته است"
-
-#, fuzzy
#~ msgid "Add Split"
#~ msgstr "اÙزودن نقطه"
diff --git a/editor/translations/fi.po b/editor/translations/fi.po
index fe2c19baa3..34eb8bac9b 100644
--- a/editor/translations/fi.po
+++ b/editor/translations/fi.po
@@ -8,14 +8,14 @@
# Jarmo Riikonen <amatrelan@gmail.com>, 2017.
# Nuutti Varvikko <nvarvikko@gmail.com>, 2018.
# Sami Lehtilä <sami.lehtila@gmail.com>, 2018.
-# Tapani Niemi <tapani.niemi@kapsi.fi>, 2018, 2019.
+# Tapani Niemi <tapani.niemi@kapsi.fi>, 2018, 2019, 2020.
# Tuomas Lähteenmäki <lahtis@gmail.com>, 2019.
msgid ""
msgstr ""
"Project-Id-Version: Godot Engine editor\n"
"POT-Creation-Date: \n"
-"PO-Revision-Date: 2019-12-23 17:08+0000\n"
-"Last-Translator: Tuomas Lähteenmäki <lahtis@gmail.com>\n"
+"PO-Revision-Date: 2020-01-03 21:21+0000\n"
+"Last-Translator: Tapani Niemi <tapani.niemi@kapsi.fi>\n"
"Language-Team: Finnish <https://hosted.weblate.org/projects/godot-engine/"
"godot/fi/>\n"
"Language: fi\n"
@@ -423,7 +423,7 @@ msgstr "Uutta raitaa ei voida lisätä ilman juurta"
#: editor/animation_track_editor.cpp
msgid "Invalid track for Bezier (no suitable sub-properties)"
-msgstr ""
+msgstr "Virheellinen raita Bezierille (ei sopivia aliominaisuuksia)"
#: editor/animation_track_editor.cpp
msgid "Add Bezier Track"
@@ -1190,10 +1190,24 @@ msgid "Error opening package file, not in ZIP format."
msgstr "Virhe avattaessa pakettitiedostoa, ei ZIP-muodossa."
#: editor/editor_asset_installer.cpp
+#, fuzzy
+msgid "%s (Already Exists)"
+msgstr "On jo olemassa"
+
+#: editor/editor_asset_installer.cpp
msgid "Uncompressing Assets"
msgstr "Puretaan assetteja"
#: editor/editor_asset_installer.cpp editor/project_manager.cpp
+msgid "The following files failed extraction from package:"
+msgstr "Seuraavien tiedostojen purku paketista epäonnistui:"
+
+#: editor/editor_asset_installer.cpp
+#, fuzzy
+msgid "And %s more files."
+msgstr "Vielä %d tiedostoa"
+
+#: editor/editor_asset_installer.cpp editor/project_manager.cpp
msgid "Package installed successfully!"
msgstr "Paketti asennettu onnistuneesti!"
@@ -1202,6 +1216,11 @@ msgstr "Paketti asennettu onnistuneesti!"
msgid "Success!"
msgstr "Onnistui!"
+#: editor/editor_asset_installer.cpp
+#, fuzzy
+msgid "Package Contents:"
+msgstr "Sisällöt:"
+
#: editor/editor_asset_installer.cpp editor/editor_node.cpp
msgid "Install"
msgstr "Asenna"
@@ -1340,6 +1359,11 @@ msgid "Invalid file, not an audio bus layout."
msgstr "Virheellinen tiedosto. Tämä ei ole ääniväylän asettelu ensinkään."
#: editor/editor_audio_buses.cpp
+#, fuzzy
+msgid "Error saving file: %s"
+msgstr "Virhe tallennettaessa tiedostoa!"
+
+#: editor/editor_audio_buses.cpp
msgid "Add Bus"
msgstr "Lisää väylä"
@@ -1995,9 +2019,8 @@ msgid "Case Sensitive"
msgstr "Merkkikokoriippuvainen"
#: editor/editor_help_search.cpp
-#, fuzzy
msgid "Show Hierarchy"
-msgstr "Näytä avustimet"
+msgstr "Näytä hierarkia"
#: editor/editor_help_search.cpp
msgid "Display All"
@@ -2036,9 +2059,8 @@ msgid "Class"
msgstr "Luokka"
#: editor/editor_help_search.cpp
-#, fuzzy
msgid "Method"
-msgstr "Metodit"
+msgstr "Metodi"
#: editor/editor_help_search.cpp editor/plugins/script_text_editor.cpp
msgid "Signal"
@@ -2049,14 +2071,12 @@ msgid "Constant"
msgstr "Muuttumaton"
#: editor/editor_help_search.cpp
-#, fuzzy
msgid "Property"
-msgstr "Ominaisuus:"
+msgstr "Ominaisuus"
#: editor/editor_help_search.cpp
-#, fuzzy
msgid "Theme Property"
-msgstr "Teeman ominaisuudet"
+msgstr "Teeman ominaisuus"
#: editor/editor_inspector.cpp editor/project_settings_editor.cpp
msgid "Property:"
@@ -2139,10 +2159,6 @@ msgid "New Window"
msgstr "Uusi ikkuna"
#: editor/editor_node.cpp
-msgid "Project export failed with error code %d."
-msgstr "Projektin vienti epäonnistui virhekoodilla %d."
-
-#: editor/editor_node.cpp
msgid "Imported resources can't be saved."
msgstr "Tuotuja resursseja ei voida tallentaa."
@@ -3049,10 +3065,6 @@ msgstr "Tuo mallit ZIP-tiedostosta"
msgid "Template Package"
msgstr "Mallipaketti"
-#: editor/editor_node.cpp editor/project_export.cpp
-msgid "Export Project"
-msgstr "Vie projekti"
-
#: editor/editor_node.cpp
msgid "Export Library"
msgstr "Vie kirjasto"
@@ -3062,10 +3074,6 @@ msgid "Merge With Existing"
msgstr "Yhdistä olemassaolevaan"
#: editor/editor_node.cpp
-msgid "Password:"
-msgstr "Salasana:"
-
-#: editor/editor_node.cpp
msgid "Open & Run a Script"
msgstr "Avaa ja suorita skripti"
@@ -3428,13 +3436,14 @@ msgid "Importing:"
msgstr "Tuodaan:"
#: editor/export_template_manager.cpp
-#, fuzzy
msgid "Error getting the list of mirrors."
-msgstr "Virhe luotaessa allekirjoitusoliota."
+msgstr "Virhe peilipalvelimien listan haussa."
#: editor/export_template_manager.cpp
msgid "Error parsing JSON of mirror list. Please report this issue!"
msgstr ""
+"Virhe jäsennettäessä peilipalvelimien JSON-listaa. Raportoi tämä ongelma, "
+"kiitos!"
#: editor/export_template_manager.cpp
msgid ""
@@ -4620,9 +4629,8 @@ msgid "Move Node"
msgstr "Siirrä solmua"
#: editor/plugins/animation_state_machine_editor.cpp
-#, fuzzy
msgid "Transition exists!"
-msgstr "Siirtymä: "
+msgstr "Siirtymä on olemassa!"
#: editor/plugins/animation_state_machine_editor.cpp
msgid "Add Transition"
@@ -5199,7 +5207,7 @@ msgstr "Vasemmassa yläkulmassa"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Top Right"
-msgstr "Oikeassa Yläkulmassa"
+msgstr "Oikeassa yläkulmassa"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Bottom Right"
@@ -5246,19 +5254,16 @@ msgid "Bottom Wide"
msgstr "Alanäkymä"
#: editor/plugins/canvas_item_editor_plugin.cpp
-#, fuzzy
msgid "VCenter Wide"
-msgstr "VCenter Wide"
+msgstr "Pystykeskitetty laaja"
#: editor/plugins/canvas_item_editor_plugin.cpp
-#, fuzzy
msgid "HCenter Wide"
-msgstr "HCenter Wide"
+msgstr "Vaakakeskitetty laaja"
#: editor/plugins/canvas_item_editor_plugin.cpp
-#, fuzzy
msgid "Full Rect"
-msgstr "Täysi toisto"
+msgstr "Täysi ruutu"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Keep Ratio"
@@ -5703,6 +5708,23 @@ msgstr "Emissiomaski"
#: editor/plugins/cpu_particles_2d_editor_plugin.cpp
#: editor/plugins/particles_2d_editor_plugin.cpp
+#, fuzzy
+msgid "Solid Pixels"
+msgstr "Kutista (pikseleissä): "
+
+#: 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
+#, fuzzy
+msgid "Directed Border Pixels"
+msgstr "Hakemistot ja tiedostot:"
+
+#: editor/plugins/cpu_particles_2d_editor_plugin.cpp
+#: editor/plugins/particles_2d_editor_plugin.cpp
msgid "Capture from Pixel"
msgstr "Nappaa pikselistä"
@@ -5928,18 +5950,19 @@ msgstr "Ääriviivojen koko:"
#: editor/plugins/mesh_instance_editor_plugin.cpp
msgid "UV Channel Debug"
-msgstr ""
+msgstr "UV-kanavan debuggaus"
#: editor/plugins/mesh_library_editor_plugin.cpp
msgid "Remove item %d?"
msgstr "Poistetaanko kohde %d?"
#: editor/plugins/mesh_library_editor_plugin.cpp
-#, fuzzy
msgid ""
"Update from existing scene?:\n"
"%s"
-msgstr "Päivitä skenestä"
+msgstr ""
+"Päivitä olemassa olevasta skenestä?:\n"
+"%s"
#: editor/plugins/mesh_library_editor_plugin.cpp
msgid "Mesh Library"
@@ -7491,9 +7514,8 @@ msgid "Create Mesh2D"
msgstr "Luo Mesh2D"
#: editor/plugins/sprite_editor_plugin.cpp
-#, fuzzy
msgid "Mesh2D Preview"
-msgstr "Luodaan meshien esikatseluita"
+msgstr "Mesh2D esikatselu"
#: editor/plugins/sprite_editor_plugin.cpp
msgid "Create Polygon2D"
@@ -7501,25 +7523,23 @@ msgstr "Luo Polygon2D"
#: editor/plugins/sprite_editor_plugin.cpp
msgid "Polygon2D Preview"
-msgstr ""
+msgstr "Polygon2D esikatselu"
#: editor/plugins/sprite_editor_plugin.cpp
msgid "Create CollisionPolygon2D"
msgstr "Luo CollisionPolygon2D"
#: editor/plugins/sprite_editor_plugin.cpp
-#, fuzzy
msgid "CollisionPolygon2D Preview"
-msgstr "Luo CollisionPolygon2D"
+msgstr "CollisionPolygon2D esikatselu"
#: editor/plugins/sprite_editor_plugin.cpp
msgid "Create LightOccluder2D"
msgstr "Luo LightOccluder2D"
#: editor/plugins/sprite_editor_plugin.cpp
-#, fuzzy
msgid "LightOccluder2D Preview"
-msgstr "Luo LightOccluder2D"
+msgstr "LightOccluder2D esikatselu"
#: editor/plugins/sprite_editor_plugin.cpp
msgid "Sprite is empty!"
@@ -7598,9 +7618,8 @@ msgid "Add Frame"
msgstr "Lisää ruutu"
#: editor/plugins/sprite_frames_editor_plugin.cpp
-#, fuzzy
msgid "Unable to load images"
-msgstr "Kuvaa ei voitu ladata:"
+msgstr "Kuvaa ei voitu ladata"
#: editor/plugins/sprite_frames_editor_plugin.cpp
msgid "ERROR: Couldn't load frame resource!"
@@ -8061,7 +8080,7 @@ msgstr "Prioriteetti"
#: editor/plugins/tile_set_editor_plugin.cpp
msgid "Z Index"
-msgstr "Z Indeksi"
+msgstr "Z-indeksi"
#: editor/plugins/tile_set_editor_plugin.cpp
msgid "Region Mode"
@@ -8290,14 +8309,12 @@ msgid "Edit Tile Z Index"
msgstr "Muokkaa ruudun Z-indeksiä"
#: editor/plugins/tile_set_editor_plugin.cpp
-#, fuzzy
msgid "Make Convex"
-msgstr "Tee polygonista konveksi"
+msgstr "Tee konveksi"
#: editor/plugins/tile_set_editor_plugin.cpp
-#, fuzzy
msgid "Make Concave"
-msgstr "Tee polygonista konkaavi"
+msgstr "Tee konkaavi"
#: editor/plugins/tile_set_editor_plugin.cpp
msgid "Create Collision Polygon"
@@ -9404,7 +9421,6 @@ msgid "Make Patch"
msgstr "Luo päivitys"
#: editor/project_export.cpp
-#, fuzzy
msgid "Pack File"
msgstr "Pakkaa tiedosto"
@@ -9453,6 +9469,10 @@ msgid "Export PCK/Zip"
msgstr "Vie PCK/Zip"
#: editor/project_export.cpp
+msgid "Export Project"
+msgstr "Vie projekti"
+
+#: editor/project_export.cpp
msgid "Export mode?"
msgstr "Vientitila?"
@@ -9547,10 +9567,6 @@ msgid "Couldn't create project.godot in project path."
msgstr "Tiedoston project.godot luonti projektin polkuun epäonnistui."
#: editor/project_manager.cpp
-msgid "The following files failed extraction from package:"
-msgstr "Seuraavien tiedostojen purku paketista epäonnistui:"
-
-#: editor/project_manager.cpp
msgid "Rename Project"
msgstr "Nimetä projekti"
@@ -10477,7 +10493,7 @@ msgstr "Käyttöliittymä"
#: editor/scene_tree_dock.cpp
msgid "Other Node"
-msgstr "Toinen solmu"
+msgstr "Muu solmu"
#: editor/scene_tree_dock.cpp
msgid "Can't operate on nodes from a foreign scene!"
@@ -10788,6 +10804,11 @@ msgid "Will load an existing script file."
msgstr "Lataa olemassaolevan skriptitiedoston."
#: editor/script_create_dialog.cpp
+#, fuzzy
+msgid "Script file already exists."
+msgstr "Jako on jo olemassa."
+
+#: editor/script_create_dialog.cpp
msgid "Class Name:"
msgstr "Luokan nimi:"
@@ -11240,9 +11261,8 @@ msgid "Cursor Clear Rotation"
msgstr "Poista kohdistimen kierto"
#: modules/gridmap/grid_map_editor_plugin.cpp
-#, fuzzy
msgid "Paste Selects"
-msgstr "Tyhjennä valittu alue"
+msgstr "Liitä valitut"
#: modules/gridmap/grid_map_editor_plugin.cpp
msgid "Clear Selection"
@@ -12457,7 +12477,15 @@ msgstr ""
"Tämä solmu on poistettu käytöstä. Käytä sen sijaan AnimationTree solmua."
#: scene/gui/color_picker.cpp
-msgid "Pick a color from the screen."
+msgid ""
+"Color: #%s\n"
+"LMB: Set color\n"
+"RMB: Remove preset"
+msgstr ""
+
+#: scene/gui/color_picker.cpp
+#, fuzzy
+msgid "Pick a color from the editor window."
msgstr "Valitse väri ruudulta."
#: scene/gui/color_picker.cpp
@@ -12580,6 +12608,12 @@ msgstr "Varying tyypin voi sijoittaa vain vertex-funktiossa."
msgid "Constants cannot be modified."
msgstr "Vakioita ei voi muokata."
+#~ msgid "Project export failed with error code %d."
+#~ msgstr "Projektin vienti epäonnistui virhekoodilla %d."
+
+#~ msgid "Password:"
+#~ msgstr "Salasana:"
+
#~ msgid "Identifier segments must be of non-zero length."
#~ msgstr "Tunnisteen osiot eivät voi olla nollan pituisia."
@@ -12931,9 +12965,6 @@ msgstr "Vakioita ei voi muokata."
#~ msgid "Create folder"
#~ msgstr "Luo kansio"
-#~ msgid "Already existing"
-#~ msgstr "On jo olemassa"
-
#~ msgid "Custom Node"
#~ msgstr "Mukautettu solmu"
@@ -12984,9 +13015,6 @@ msgstr "Vakioita ei voi muokata."
#~ msgid "Split can't form an existing edge."
#~ msgstr "Jako ei voi muodostaa olemassa olevaa reunaa."
-#~ msgid "Split already exists."
-#~ msgstr "Jako on jo olemassa."
-
#~ msgid "Add Split"
#~ msgstr "Lisää jako"
diff --git a/editor/translations/fil.po b/editor/translations/fil.po
index abe6c7ad16..b77c4714dd 100644
--- a/editor/translations/fil.po
+++ b/editor/translations/fil.po
@@ -1162,10 +1162,22 @@ msgid "Error opening package file, not in ZIP format."
msgstr ""
#: editor/editor_asset_installer.cpp
+msgid "%s (Already Exists)"
+msgstr ""
+
+#: editor/editor_asset_installer.cpp
msgid "Uncompressing Assets"
msgstr ""
#: editor/editor_asset_installer.cpp editor/project_manager.cpp
+msgid "The following files failed extraction from package:"
+msgstr ""
+
+#: editor/editor_asset_installer.cpp
+msgid "And %s more files."
+msgstr ""
+
+#: editor/editor_asset_installer.cpp editor/project_manager.cpp
msgid "Package installed successfully!"
msgstr ""
@@ -1174,6 +1186,10 @@ msgstr ""
msgid "Success!"
msgstr ""
+#: editor/editor_asset_installer.cpp
+msgid "Package Contents:"
+msgstr ""
+
#: editor/editor_asset_installer.cpp editor/editor_node.cpp
msgid "Install"
msgstr ""
@@ -1312,6 +1328,10 @@ msgid "Invalid file, not an audio bus layout."
msgstr ""
#: editor/editor_audio_buses.cpp
+msgid "Error saving file: %s"
+msgstr ""
+
+#: editor/editor_audio_buses.cpp
msgid "Add Bus"
msgstr ""
@@ -2084,10 +2104,6 @@ msgid "New Window"
msgstr ""
#: editor/editor_node.cpp
-msgid "Project export failed with error code %d."
-msgstr ""
-
-#: editor/editor_node.cpp
msgid "Imported resources can't be saved."
msgstr ""
@@ -2927,10 +2943,6 @@ msgstr ""
msgid "Template Package"
msgstr ""
-#: editor/editor_node.cpp editor/project_export.cpp
-msgid "Export Project"
-msgstr ""
-
#: editor/editor_node.cpp
msgid "Export Library"
msgstr ""
@@ -2940,10 +2952,6 @@ msgid "Merge With Existing"
msgstr ""
#: editor/editor_node.cpp
-msgid "Password:"
-msgstr ""
-
-#: editor/editor_node.cpp
msgid "Open & Run a Script"
msgstr ""
@@ -5508,6 +5516,21 @@ 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 ""
@@ -9130,6 +9153,10 @@ msgid "Export PCK/Zip"
msgstr ""
#: editor/project_export.cpp
+msgid "Export Project"
+msgstr ""
+
+#: editor/project_export.cpp
msgid "Export mode?"
msgstr ""
@@ -9220,10 +9247,6 @@ msgid "Couldn't create project.godot in project path."
msgstr ""
#: editor/project_manager.cpp
-msgid "The following files failed extraction from package:"
-msgstr ""
-
-#: editor/project_manager.cpp
msgid "Rename Project"
msgstr ""
@@ -10382,6 +10405,10 @@ msgid "Will load an existing script file."
msgstr ""
#: editor/script_create_dialog.cpp
+msgid "Script file already exists."
+msgstr ""
+
+#: editor/script_create_dialog.cpp
msgid "Class Name:"
msgstr ""
@@ -11912,7 +11939,14 @@ msgid "This node has been deprecated. Use AnimationTree instead."
msgstr ""
#: scene/gui/color_picker.cpp
-msgid "Pick a color from the screen."
+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
diff --git a/editor/translations/fr.po b/editor/translations/fr.po
index cbb6aeae7b..3b761bb777 100644
--- a/editor/translations/fr.po
+++ b/editor/translations/fr.po
@@ -49,7 +49,7 @@
# Brice Lobet <tempo.data@gmail.com>, 2018.
# Florent Wijanto <f_wijanto@hotmail.com>, 2018.
# Olivier gareau <olivier.gareau@protonmail.com>, 2018.
-# Rémi Verschelde <akien@godotengine.org>, 2018, 2019.
+# Rémi Verschelde <akien@godotengine.org>, 2018, 2019, 2020.
# Rémi Bintein <reminus5@hotmail.fr>, 2018, 2019.
# Sylvain Corsini <sylvain.corsini@gmail.com>, 2018.
# Caye Pierre <pierrecaye@laposte.net>, 2019.
@@ -73,8 +73,8 @@ msgid ""
msgstr ""
"Project-Id-Version: Godot Engine editor\n"
"POT-Creation-Date: \n"
-"PO-Revision-Date: 2019-12-23 17:08+0000\n"
-"Last-Translator: Camille Mohr-Daurat <pouleyketchoup@gmail.com>\n"
+"PO-Revision-Date: 2020-01-03 21:21+0000\n"
+"Last-Translator: Rémi Verschelde <akien@godotengine.org>\n"
"Language-Team: French <https://hosted.weblate.org/projects/godot-engine/"
"godot/fr/>\n"
"Language: fr\n"
@@ -487,7 +487,7 @@ msgstr "Impossible d'ajouter une nouvelle piste sans racine"
#: editor/animation_track_editor.cpp
msgid "Invalid track for Bezier (no suitable sub-properties)"
-msgstr ""
+msgstr "Piste invalide pour Bézier (aucune sous-propriété appropriée)"
#: editor/animation_track_editor.cpp
msgid "Add Bezier Track"
@@ -1264,10 +1264,24 @@ msgid "Error opening package file, not in ZIP format."
msgstr "Erreur d'ouverture de paquetage, pas au format ZIP."
#: editor/editor_asset_installer.cpp
+#, fuzzy
+msgid "%s (Already Exists)"
+msgstr "Existe déjà"
+
+#: editor/editor_asset_installer.cpp
msgid "Uncompressing Assets"
msgstr "Décompression des assets"
#: editor/editor_asset_installer.cpp editor/project_manager.cpp
+msgid "The following files failed extraction from package:"
+msgstr "L'extraction des fichiers suivants depuis le paquetage a échoué :"
+
+#: editor/editor_asset_installer.cpp
+#, fuzzy
+msgid "And %s more files."
+msgstr "%d fichiers supplémentaires"
+
+#: editor/editor_asset_installer.cpp editor/project_manager.cpp
msgid "Package installed successfully!"
msgstr "Paquetage installé avec succès !"
@@ -1276,6 +1290,11 @@ msgstr "Paquetage installé avec succès !"
msgid "Success!"
msgstr "Ça marche !"
+#: editor/editor_asset_installer.cpp
+#, fuzzy
+msgid "Package Contents:"
+msgstr "Contenu :"
+
#: editor/editor_asset_installer.cpp editor/editor_node.cpp
msgid "Install"
msgstr "Installer"
@@ -1414,6 +1433,11 @@ msgid "Invalid file, not an audio bus layout."
msgstr "Fichier invalide, pas une disposition de bus audio."
#: editor/editor_audio_buses.cpp
+#, fuzzy
+msgid "Error saving file: %s"
+msgstr "Erreur lors de l'enregistrement du fichier !"
+
+#: editor/editor_audio_buses.cpp
msgid "Add Bus"
msgstr "Ajouter un bus"
@@ -2064,14 +2088,12 @@ msgid "Search Help"
msgstr "Rechercher dans l'aide"
#: editor/editor_help_search.cpp
-#, fuzzy
msgid "Case Sensitive"
-msgstr "Fermer la scène"
+msgstr "Sensible à la casse"
#: editor/editor_help_search.cpp
-#, fuzzy
msgid "Show Hierarchy"
-msgstr "Afficher les aides"
+msgstr "Afficher la hiérarchie"
#: editor/editor_help_search.cpp
msgid "Display All"
@@ -2110,9 +2132,8 @@ msgid "Class"
msgstr "Classe :"
#: editor/editor_help_search.cpp
-#, fuzzy
msgid "Method"
-msgstr "Méthodes"
+msgstr "Méthode"
#: editor/editor_help_search.cpp editor/plugins/script_text_editor.cpp
msgid "Signal"
@@ -2123,14 +2144,12 @@ msgid "Constant"
msgstr "Constante"
#: editor/editor_help_search.cpp
-#, fuzzy
msgid "Property"
-msgstr "Propriété :"
+msgstr "Propriété"
#: editor/editor_help_search.cpp
-#, fuzzy
msgid "Theme Property"
-msgstr "Propriétés du thème"
+msgstr "Propriété du thème"
#: editor/editor_inspector.cpp editor/project_settings_editor.cpp
msgid "Property:"
@@ -2213,10 +2232,6 @@ msgid "New Window"
msgstr "Nouvelle Fenêtre"
#: editor/editor_node.cpp
-msgid "Project export failed with error code %d."
-msgstr "L'export du projet a échoué avec le code erreur %d."
-
-#: editor/editor_node.cpp
msgid "Imported resources can't be saved."
msgstr "Les ressources importés ne peuvent pas être sauvegarder."
@@ -3152,10 +3167,6 @@ msgstr "Importer des modèles depuis un fichier ZIP"
msgid "Template Package"
msgstr "Paquet de modèle"
-#: editor/editor_node.cpp editor/project_export.cpp
-msgid "Export Project"
-msgstr "Exporter le projet"
-
#: editor/editor_node.cpp
msgid "Export Library"
msgstr "Bibliothèque d'exportation"
@@ -3165,10 +3176,6 @@ msgid "Merge With Existing"
msgstr "Fusionner avec l'existant"
#: editor/editor_node.cpp
-msgid "Password:"
-msgstr "Mot de passe :"
-
-#: editor/editor_node.cpp
msgid "Open & Run a Script"
msgstr "Ouvrir et exécuter un script"
@@ -3535,11 +3542,13 @@ msgstr "Importation :"
#: editor/export_template_manager.cpp
msgid "Error getting the list of mirrors."
-msgstr ""
+msgstr "Erreur lors du téléchargement de la liste des miroirs."
#: editor/export_template_manager.cpp
msgid "Error parsing JSON of mirror list. Please report this issue!"
msgstr ""
+"Erreur lors de la lecture de la liste JSON des miroirs. Merci de signaler ce "
+"problème !"
#: editor/export_template_manager.cpp
msgid ""
@@ -4734,9 +4743,8 @@ msgid "Move Node"
msgstr "Déplacer le nœud"
#: editor/plugins/animation_state_machine_editor.cpp
-#, fuzzy
msgid "Transition exists!"
-msgstr "Transition : "
+msgstr "La transition existe !"
#: editor/plugins/animation_state_machine_editor.cpp
msgid "Add Transition"
@@ -5816,6 +5824,23 @@ msgstr "Masque d'émission"
#: editor/plugins/cpu_particles_2d_editor_plugin.cpp
#: editor/plugins/particles_2d_editor_plugin.cpp
+#, fuzzy
+msgid "Solid Pixels"
+msgstr "Rétrécir (Pixels) : "
+
+#: 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
+#, fuzzy
+msgid "Directed Border Pixels"
+msgstr "Répertoires et fichiers :"
+
+#: editor/plugins/cpu_particles_2d_editor_plugin.cpp
+#: editor/plugins/particles_2d_editor_plugin.cpp
msgid "Capture from Pixel"
msgstr "Capturer depuis Pixel"
@@ -6044,18 +6069,19 @@ msgstr "Taille du contour :"
#: editor/plugins/mesh_instance_editor_plugin.cpp
msgid "UV Channel Debug"
-msgstr ""
+msgstr "Débogage du canal UV"
#: editor/plugins/mesh_library_editor_plugin.cpp
msgid "Remove item %d?"
msgstr "Supprimer l'objet %d ?"
#: editor/plugins/mesh_library_editor_plugin.cpp
-#, fuzzy
msgid ""
"Update from existing scene?:\n"
"%s"
-msgstr "Mettre à jour depuis la scène"
+msgstr ""
+"Mettre à jour depuis la scène existante ?\n"
+"%s"
#: editor/plugins/mesh_library_editor_plugin.cpp
msgid "Mesh Library"
@@ -7616,9 +7642,8 @@ msgid "Create Mesh2D"
msgstr "Créer un Mesh2D"
#: editor/plugins/sprite_editor_plugin.cpp
-#, fuzzy
msgid "Mesh2D Preview"
-msgstr "Création des prévisualisations des maillages"
+msgstr "Prévisualisation du Mesh2D"
#: editor/plugins/sprite_editor_plugin.cpp
msgid "Create Polygon2D"
@@ -7626,25 +7651,23 @@ msgstr "Créer un Polygon2D"
#: editor/plugins/sprite_editor_plugin.cpp
msgid "Polygon2D Preview"
-msgstr ""
+msgstr "Prévisualisation du Polygon2D"
#: editor/plugins/sprite_editor_plugin.cpp
msgid "Create CollisionPolygon2D"
msgstr "Créer un CollisionPolygon2D"
#: editor/plugins/sprite_editor_plugin.cpp
-#, fuzzy
msgid "CollisionPolygon2D Preview"
-msgstr "Créer un CollisionPolygon2D"
+msgstr "Prévisualisation du CollisionPolygon2D"
#: editor/plugins/sprite_editor_plugin.cpp
msgid "Create LightOccluder2D"
msgstr "Créer un LightOccluder2D"
#: editor/plugins/sprite_editor_plugin.cpp
-#, fuzzy
msgid "LightOccluder2D Preview"
-msgstr "Créer un LightOccluder2D"
+msgstr "Prévisualisation du LightOccluder2D"
#: editor/plugins/sprite_editor_plugin.cpp
msgid "Sprite is empty!"
@@ -7725,9 +7748,8 @@ msgid "Add Frame"
msgstr "Ajouter une image"
#: editor/plugins/sprite_frames_editor_plugin.cpp
-#, fuzzy
msgid "Unable to load images"
-msgstr "Impossible de charger la ressource."
+msgstr "Impossible de charger les images"
#: editor/plugins/sprite_frames_editor_plugin.cpp
msgid "ERROR: Couldn't load frame resource!"
@@ -8417,12 +8439,10 @@ msgid "Edit Tile Z Index"
msgstr "Modifier l'index Z de la tuile"
#: editor/plugins/tile_set_editor_plugin.cpp
-#, fuzzy
msgid "Make Convex"
-msgstr "Rendre le polygon Convex"
+msgstr "Rendre le polygone convexe"
#: editor/plugins/tile_set_editor_plugin.cpp
-#, fuzzy
msgid "Make Concave"
msgstr "Rendre le polygone concave"
@@ -9589,6 +9609,10 @@ msgid "Export PCK/Zip"
msgstr "Exporter le PCK/ZIP"
#: editor/project_export.cpp
+msgid "Export Project"
+msgstr "Exporter le projet"
+
+#: editor/project_export.cpp
msgid "Export mode?"
msgstr "Mode d'exportation ?"
@@ -9684,10 +9708,6 @@ msgid "Couldn't create project.godot in project path."
msgstr "Impossible de créer le fichier project.godot dans le chemin du projet."
#: editor/project_manager.cpp
-msgid "The following files failed extraction from package:"
-msgstr "L'extraction des fichiers suivants depuis le paquetage a échoué :"
-
-#: editor/project_manager.cpp
msgid "Rename Project"
msgstr "Renommer le projet"
@@ -10928,6 +10948,11 @@ msgid "Will load an existing script file."
msgstr "Va charger un fichier de script existant."
#: editor/script_create_dialog.cpp
+#, fuzzy
+msgid "Script file already exists."
+msgstr "Le fractionnement existe déjà."
+
+#: editor/script_create_dialog.cpp
msgid "Class Name:"
msgstr "Nom de la classe :"
@@ -11381,9 +11406,8 @@ msgid "Cursor Clear Rotation"
msgstr "Effacer rotation curseur"
#: modules/gridmap/grid_map_editor_plugin.cpp
-#, fuzzy
msgid "Paste Selects"
-msgstr "Supprimer la sélection"
+msgstr "Sélectionner lors d'un collage"
#: modules/gridmap/grid_map_editor_plugin.cpp
msgid "Clear Selection"
@@ -12634,7 +12658,15 @@ msgid "This node has been deprecated. Use AnimationTree instead."
msgstr "Ce nœud est désormais déprécié. Utilisez AnimationTree à la place."
#: scene/gui/color_picker.cpp
-msgid "Pick a color from the screen."
+msgid ""
+"Color: #%s\n"
+"LMB: Set color\n"
+"RMB: Remove preset"
+msgstr ""
+
+#: scene/gui/color_picker.cpp
+#, fuzzy
+msgid "Pick a color from the editor window."
msgstr "Échantillonner une couleur depuis l'écran."
#: scene/gui/color_picker.cpp
@@ -12759,6 +12791,12 @@ 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 "Project export failed with error code %d."
+#~ msgstr "L'export du projet a échoué avec le code erreur %d."
+
+#~ msgid "Password:"
+#~ msgstr "Mot de passe :"
+
#~ msgid "Identifier segments must be of non-zero length."
#~ msgstr ""
#~ "Les segments de l'identifiant doivent être d'une longueur supérieure à "
@@ -13056,9 +13094,6 @@ msgstr "Les constantes ne peuvent être modifiées."
#~ msgid "Create folder"
#~ msgstr "Créer dossier"
-#~ msgid "Already existing"
-#~ msgstr "Existe déjà"
-
#~ msgid "Custom Node"
#~ msgstr "Nœud personnalisé"
@@ -13111,9 +13146,6 @@ msgstr "Les constantes ne peuvent être modifiées."
#~ msgid "Split can't form an existing edge."
#~ msgstr "Le fractionnement ne peut pas former une arête existante."
-#~ msgid "Split already exists."
-#~ msgstr "Le fractionnement existe déjà."
-
#~ msgid "Add Split"
#~ msgstr "Ajouter un fractionnement"
diff --git a/editor/translations/ga.po b/editor/translations/ga.po
index f60101096c..b0876790ee 100644
--- a/editor/translations/ga.po
+++ b/editor/translations/ga.po
@@ -1156,10 +1156,22 @@ msgid "Error opening package file, not in ZIP format."
msgstr ""
#: editor/editor_asset_installer.cpp
+msgid "%s (Already Exists)"
+msgstr ""
+
+#: editor/editor_asset_installer.cpp
msgid "Uncompressing Assets"
msgstr ""
#: editor/editor_asset_installer.cpp editor/project_manager.cpp
+msgid "The following files failed extraction from package:"
+msgstr ""
+
+#: editor/editor_asset_installer.cpp
+msgid "And %s more files."
+msgstr ""
+
+#: editor/editor_asset_installer.cpp editor/project_manager.cpp
msgid "Package installed successfully!"
msgstr ""
@@ -1168,6 +1180,11 @@ msgstr ""
msgid "Success!"
msgstr ""
+#: editor/editor_asset_installer.cpp
+#, fuzzy
+msgid "Package Contents:"
+msgstr "Ãbhar:"
+
#: editor/editor_asset_installer.cpp editor/editor_node.cpp
msgid "Install"
msgstr ""
@@ -1306,6 +1323,10 @@ msgid "Invalid file, not an audio bus layout."
msgstr ""
#: editor/editor_audio_buses.cpp
+msgid "Error saving file: %s"
+msgstr ""
+
+#: editor/editor_audio_buses.cpp
msgid "Add Bus"
msgstr ""
@@ -2079,10 +2100,6 @@ msgid "New Window"
msgstr ""
#: editor/editor_node.cpp
-msgid "Project export failed with error code %d."
-msgstr ""
-
-#: editor/editor_node.cpp
msgid "Imported resources can't be saved."
msgstr ""
@@ -2921,10 +2938,6 @@ msgstr ""
msgid "Template Package"
msgstr ""
-#: editor/editor_node.cpp editor/project_export.cpp
-msgid "Export Project"
-msgstr ""
-
#: editor/editor_node.cpp
msgid "Export Library"
msgstr ""
@@ -2934,10 +2947,6 @@ msgid "Merge With Existing"
msgstr ""
#: editor/editor_node.cpp
-msgid "Password:"
-msgstr ""
-
-#: editor/editor_node.cpp
msgid "Open & Run a Script"
msgstr ""
@@ -5504,6 +5513,21 @@ 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 ""
@@ -9125,6 +9149,10 @@ msgid "Export PCK/Zip"
msgstr ""
#: editor/project_export.cpp
+msgid "Export Project"
+msgstr ""
+
+#: editor/project_export.cpp
msgid "Export mode?"
msgstr ""
@@ -9215,10 +9243,6 @@ msgid "Couldn't create project.godot in project path."
msgstr ""
#: editor/project_manager.cpp
-msgid "The following files failed extraction from package:"
-msgstr ""
-
-#: editor/project_manager.cpp
msgid "Rename Project"
msgstr ""
@@ -10377,6 +10401,10 @@ msgid "Will load an existing script file."
msgstr ""
#: editor/script_create_dialog.cpp
+msgid "Script file already exists."
+msgstr ""
+
+#: editor/script_create_dialog.cpp
msgid "Class Name:"
msgstr ""
@@ -11908,7 +11936,14 @@ msgid "This node has been deprecated. Use AnimationTree instead."
msgstr ""
#: scene/gui/color_picker.cpp
-msgid "Pick a color from the screen."
+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
diff --git a/editor/translations/he.po b/editor/translations/he.po
index 66c0a8fa89..18a22b51be 100644
--- a/editor/translations/he.po
+++ b/editor/translations/he.po
@@ -1227,10 +1227,23 @@ msgid "Error opening package file, not in ZIP format."
msgstr "פתיחת קובץ החבילה נכשלה, המבנה ×ינו zip."
#: editor/editor_asset_installer.cpp
+#, fuzzy
+msgid "%s (Already Exists)"
+msgstr "הפעולה ‚%s’ כבר קיימת!"
+
+#: editor/editor_asset_installer.cpp
msgid "Uncompressing Assets"
msgstr ""
#: editor/editor_asset_installer.cpp editor/project_manager.cpp
+msgid "The following files failed extraction from package:"
+msgstr ""
+
+#: editor/editor_asset_installer.cpp
+msgid "And %s more files."
+msgstr ""
+
+#: editor/editor_asset_installer.cpp editor/project_manager.cpp
#, fuzzy
msgid "Package installed successfully!"
msgstr "החבילה הותקנה בהצלחה!"
@@ -1240,6 +1253,11 @@ msgstr "החבילה הותקנה בהצלחה!"
msgid "Success!"
msgstr "הצלחה!"
+#: editor/editor_asset_installer.cpp
+#, fuzzy
+msgid "Package Contents:"
+msgstr "מתקין החבילות"
+
#: editor/editor_asset_installer.cpp editor/editor_node.cpp
msgid "Install"
msgstr "התקנה"
@@ -1379,6 +1397,11 @@ msgid "Invalid file, not an audio bus layout."
msgstr "קובץ שגוי, ×œ× ×¤×¨×™×¡×” של ×פיקי שמע."
#: editor/editor_audio_buses.cpp
+#, fuzzy
+msgid "Error saving file: %s"
+msgstr "שגי××” בשמירה"
+
+#: editor/editor_audio_buses.cpp
msgid "Add Bus"
msgstr "הוספת ×פיק"
@@ -2215,10 +2238,6 @@ msgid "New Window"
msgstr ""
#: editor/editor_node.cpp
-msgid "Project export failed with error code %d."
-msgstr ""
-
-#: editor/editor_node.cpp
msgid "Imported resources can't be saved."
msgstr ""
@@ -3096,10 +3115,6 @@ msgstr "×™×™×‘×•× ×ª×‘× ×™×•×ª מקובץ ZIP"
msgid "Template Package"
msgstr "מנהל ×™×™×¦×•× ×ª×‘× ×™×•×ª"
-#: editor/editor_node.cpp editor/project_export.cpp
-msgid "Export Project"
-msgstr "×™×™×¦×•× ×ž×™×–×"
-
#: editor/editor_node.cpp
msgid "Export Library"
msgstr "×™×™×¦×•× ×¡×¤×¨×™×”"
@@ -3109,10 +3124,6 @@ msgid "Merge With Existing"
msgstr "מיזוג ×¢× × ×•×›×—×™×™×"
#: editor/editor_node.cpp
-msgid "Password:"
-msgstr "ססמה:"
-
-#: editor/editor_node.cpp
msgid "Open & Run a Script"
msgstr "פתיחה והרצה של סקריפט"
@@ -5840,6 +5851,22 @@ 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
+#, fuzzy
+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 ""
@@ -9658,6 +9685,10 @@ msgid "Export PCK/Zip"
msgstr ""
#: editor/project_export.cpp
+msgid "Export Project"
+msgstr "×™×™×¦×•× ×ž×™×–×"
+
+#: editor/project_export.cpp
#, fuzzy
msgid "Export mode?"
msgstr "×™×™×¦×•× ×ž×™×–×"
@@ -9752,10 +9783,6 @@ msgid "Couldn't create project.godot in project path."
msgstr ""
#: editor/project_manager.cpp
-msgid "The following files failed extraction from package:"
-msgstr ""
-
-#: editor/project_manager.cpp
msgid "Rename Project"
msgstr ""
@@ -10974,6 +11001,11 @@ msgstr "טעינת פריסת ×פיקי שמע."
#: editor/script_create_dialog.cpp
#, fuzzy
+msgid "Script file already exists."
+msgstr "הפעולה ‚%s’ כבר קיימת!"
+
+#: editor/script_create_dialog.cpp
+#, fuzzy
msgid "Class Name:"
msgstr "מחלקה:"
@@ -12555,7 +12587,14 @@ msgid "This node has been deprecated. Use AnimationTree instead."
msgstr ""
#: scene/gui/color_picker.cpp
-msgid "Pick a color from the screen."
+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
@@ -12663,6 +12702,9 @@ msgstr ""
msgid "Constants cannot be modified."
msgstr ""
+#~ msgid "Password:"
+#~ msgstr "ססמה:"
+
#~ msgid "Pause the scene"
#~ msgstr "השהיית הסצנה"
@@ -12835,10 +12877,6 @@ msgstr ""
#~ msgstr "PathFollow2D עובד רק ×›×שר ×”×•× ×ž×•×’×“×¨ כצ××¦× ×©×œ מפרק Path2D."
#, fuzzy
-#~ msgid "Split already exists."
-#~ msgstr "הפעולה ‚%s’ כבר קיימת!"
-
-#, fuzzy
#~ msgid "Remove Split"
#~ msgstr "הסרת תבנית"
diff --git a/editor/translations/hi.po b/editor/translations/hi.po
index 20f3837208..b46c89c8eb 100644
--- a/editor/translations/hi.po
+++ b/editor/translations/hi.po
@@ -1231,10 +1231,22 @@ msgid "Error opening package file, not in ZIP format."
msgstr "पैकेज फ़ाइल खोलने में तà¥à¤°à¥à¤Ÿà¤¿, zip पà¥à¤°à¤¾à¤°à¥‚प में नहीं |"
#: editor/editor_asset_installer.cpp
+msgid "%s (Already Exists)"
+msgstr ""
+
+#: editor/editor_asset_installer.cpp
msgid "Uncompressing Assets"
msgstr "असंपीड़ित संपतà¥à¤¤à¤¿à¤¯à¤¾à¤‚"
#: editor/editor_asset_installer.cpp editor/project_manager.cpp
+msgid "The following files failed extraction from package:"
+msgstr ""
+
+#: editor/editor_asset_installer.cpp
+msgid "And %s more files."
+msgstr ""
+
+#: editor/editor_asset_installer.cpp editor/project_manager.cpp
#, fuzzy
msgid "Package installed successfully!"
msgstr "पैकेज सफलतापूरà¥à¤µà¤• सà¥à¤¥à¤¾à¤ªà¤¿à¤¤ किया गया!"
@@ -1244,6 +1256,11 @@ msgstr "पैकेज सफलतापूरà¥à¤µà¤• सà¥à¤¥à¤¾à¤ªà¤¿à¤¤
msgid "Success!"
msgstr "सफलता!"
+#: editor/editor_asset_installer.cpp
+#, fuzzy
+msgid "Package Contents:"
+msgstr "Package Installer"
+
#: editor/editor_asset_installer.cpp editor/editor_node.cpp
msgid "Install"
msgstr "इंसà¥à¤Ÿà¥‰à¤²"
@@ -1388,6 +1405,11 @@ msgid "Invalid file, not an audio bus layout."
msgstr ""
#: editor/editor_audio_buses.cpp
+#, fuzzy
+msgid "Error saving file: %s"
+msgstr "लोड हो रहा है तà¥à¤°à¥à¤Ÿà¤¿à¤¯à¤¾à¤!"
+
+#: editor/editor_audio_buses.cpp
msgid "Add Bus"
msgstr ""
@@ -2177,10 +2199,6 @@ msgid "New Window"
msgstr ""
#: editor/editor_node.cpp
-msgid "Project export failed with error code %d."
-msgstr ""
-
-#: editor/editor_node.cpp
msgid "Imported resources can't be saved."
msgstr ""
@@ -3028,10 +3046,6 @@ msgstr ""
msgid "Template Package"
msgstr ""
-#: editor/editor_node.cpp editor/project_export.cpp
-msgid "Export Project"
-msgstr ""
-
#: editor/editor_node.cpp
msgid "Export Library"
msgstr ""
@@ -3041,10 +3055,6 @@ msgid "Merge With Existing"
msgstr ""
#: editor/editor_node.cpp
-msgid "Password:"
-msgstr ""
-
-#: editor/editor_node.cpp
msgid "Open & Run a Script"
msgstr ""
@@ -5676,6 +5686,21 @@ 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 ""
@@ -9382,6 +9407,10 @@ msgid "Export PCK/Zip"
msgstr ""
#: editor/project_export.cpp
+msgid "Export Project"
+msgstr ""
+
+#: editor/project_export.cpp
msgid "Export mode?"
msgstr ""
@@ -9473,10 +9502,6 @@ msgid "Couldn't create project.godot in project path."
msgstr ""
#: editor/project_manager.cpp
-msgid "The following files failed extraction from package:"
-msgstr ""
-
-#: editor/project_manager.cpp
msgid "Rename Project"
msgstr ""
@@ -10655,6 +10680,10 @@ msgid "Will load an existing script file."
msgstr ""
#: editor/script_create_dialog.cpp
+msgid "Script file already exists."
+msgstr ""
+
+#: editor/script_create_dialog.cpp
msgid "Class Name:"
msgstr ""
@@ -12214,7 +12243,14 @@ msgid "This node has been deprecated. Use AnimationTree instead."
msgstr ""
#: scene/gui/color_picker.cpp
-msgid "Pick a color from the screen."
+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
diff --git a/editor/translations/hr.po b/editor/translations/hr.po
index 09ae51b66d..f1a7f46b69 100644
--- a/editor/translations/hr.po
+++ b/editor/translations/hr.po
@@ -1170,10 +1170,22 @@ msgid "Error opening package file, not in ZIP format."
msgstr "Pogreška prilikom otvaranja datoteke paketa, nije u ZIP formatu."
#: editor/editor_asset_installer.cpp
+msgid "%s (Already Exists)"
+msgstr ""
+
+#: editor/editor_asset_installer.cpp
msgid "Uncompressing Assets"
msgstr ""
#: editor/editor_asset_installer.cpp editor/project_manager.cpp
+msgid "The following files failed extraction from package:"
+msgstr ""
+
+#: editor/editor_asset_installer.cpp
+msgid "And %s more files."
+msgstr ""
+
+#: editor/editor_asset_installer.cpp editor/project_manager.cpp
msgid "Package installed successfully!"
msgstr "Paket uspješno instaliran!"
@@ -1182,6 +1194,10 @@ msgstr "Paket uspješno instaliran!"
msgid "Success!"
msgstr "Uspjeh!"
+#: editor/editor_asset_installer.cpp
+msgid "Package Contents:"
+msgstr ""
+
#: editor/editor_asset_installer.cpp editor/editor_node.cpp
msgid "Install"
msgstr "Instaliraj"
@@ -1320,6 +1336,11 @@ msgid "Invalid file, not an audio bus layout."
msgstr ""
#: editor/editor_audio_buses.cpp
+#, fuzzy
+msgid "Error saving file: %s"
+msgstr "PogreÅ¡ka uÄitavanja:"
+
+#: editor/editor_audio_buses.cpp
msgid "Add Bus"
msgstr ""
@@ -2094,10 +2115,6 @@ msgid "New Window"
msgstr ""
#: editor/editor_node.cpp
-msgid "Project export failed with error code %d."
-msgstr ""
-
-#: editor/editor_node.cpp
msgid "Imported resources can't be saved."
msgstr ""
@@ -2937,10 +2954,6 @@ msgstr ""
msgid "Template Package"
msgstr ""
-#: editor/editor_node.cpp editor/project_export.cpp
-msgid "Export Project"
-msgstr ""
-
#: editor/editor_node.cpp
msgid "Export Library"
msgstr ""
@@ -2950,10 +2963,6 @@ msgid "Merge With Existing"
msgstr ""
#: editor/editor_node.cpp
-msgid "Password:"
-msgstr ""
-
-#: editor/editor_node.cpp
msgid "Open & Run a Script"
msgstr ""
@@ -5528,6 +5537,22 @@ 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
+#, fuzzy
+msgid "Directed Border Pixels"
+msgstr "Direktoriji i datoteke:"
+
+#: editor/plugins/cpu_particles_2d_editor_plugin.cpp
+#: editor/plugins/particles_2d_editor_plugin.cpp
msgid "Capture from Pixel"
msgstr ""
@@ -9166,6 +9191,10 @@ msgid "Export PCK/Zip"
msgstr ""
#: editor/project_export.cpp
+msgid "Export Project"
+msgstr ""
+
+#: editor/project_export.cpp
msgid "Export mode?"
msgstr ""
@@ -9257,10 +9286,6 @@ msgid "Couldn't create project.godot in project path."
msgstr ""
#: editor/project_manager.cpp
-msgid "The following files failed extraction from package:"
-msgstr ""
-
-#: editor/project_manager.cpp
msgid "Rename Project"
msgstr ""
@@ -10423,6 +10448,10 @@ msgid "Will load an existing script file."
msgstr ""
#: editor/script_create_dialog.cpp
+msgid "Script file already exists."
+msgstr ""
+
+#: editor/script_create_dialog.cpp
msgid "Class Name:"
msgstr ""
@@ -11963,7 +11992,14 @@ msgid "This node has been deprecated. Use AnimationTree instead."
msgstr ""
#: scene/gui/color_picker.cpp
-msgid "Pick a color from the screen."
+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
diff --git a/editor/translations/hu.po b/editor/translations/hu.po
index 90330ac2d6..6571cdfcc6 100644
--- a/editor/translations/hu.po
+++ b/editor/translations/hu.po
@@ -1243,10 +1243,24 @@ msgid "Error opening package file, not in ZIP format."
msgstr "Hiba a csomagfájl megnyitása során, nem zip formátumú."
#: editor/editor_asset_installer.cpp
+#, fuzzy
+msgid "%s (Already Exists)"
+msgstr "Már létezik '%s' AutoLoad!"
+
+#: editor/editor_asset_installer.cpp
msgid "Uncompressing Assets"
msgstr "Eszközök Kicsomagolása"
#: editor/editor_asset_installer.cpp editor/project_manager.cpp
+msgid "The following files failed extraction from package:"
+msgstr ""
+
+#: editor/editor_asset_installer.cpp
+#, fuzzy
+msgid "And %s more files."
+msgstr "%d további fájl"
+
+#: editor/editor_asset_installer.cpp editor/project_manager.cpp
#, fuzzy
msgid "Package installed successfully!"
msgstr "A Csomag Telepítése Sikeresen Megtörtént!"
@@ -1256,6 +1270,11 @@ msgstr "A Csomag Telepítése Sikeresen Megtörtént!"
msgid "Success!"
msgstr "Siker!"
+#: editor/editor_asset_installer.cpp
+#, fuzzy
+msgid "Package Contents:"
+msgstr "Tartalom:"
+
#: editor/editor_asset_installer.cpp editor/editor_node.cpp
msgid "Install"
msgstr "Telepítés"
@@ -1395,6 +1414,11 @@ msgid "Invalid file, not an audio bus layout."
msgstr "Érvénytelen fájl, nem egy hangbusz elrendezés."
#: editor/editor_audio_buses.cpp
+#, fuzzy
+msgid "Error saving file: %s"
+msgstr "Hiba TileSet mentésekor!"
+
+#: editor/editor_audio_buses.cpp
msgid "Add Bus"
msgstr "Busz Hozzáadása"
@@ -2241,10 +2265,6 @@ msgid "New Window"
msgstr ""
#: editor/editor_node.cpp
-msgid "Project export failed with error code %d."
-msgstr "Projekt export nem sikerült, hibakód %d."
-
-#: editor/editor_node.cpp
msgid "Imported resources can't be saved."
msgstr ""
@@ -3189,10 +3209,6 @@ msgstr "Sablonok Importálása ZIP Fájlból"
msgid "Template Package"
msgstr "Export Sablon Kezelő"
-#: editor/editor_node.cpp editor/project_export.cpp
-msgid "Export Project"
-msgstr "Projekt Exportálása"
-
#: editor/editor_node.cpp
msgid "Export Library"
msgstr "Könyvtár Exportálása"
@@ -3202,10 +3218,6 @@ msgid "Merge With Existing"
msgstr "Egyesítés Meglévővel"
#: editor/editor_node.cpp
-msgid "Password:"
-msgstr "Jelszó:"
-
-#: editor/editor_node.cpp
msgid "Open & Run a Script"
msgstr "Szkriptet Megnyit és Futtat"
@@ -5988,6 +6000,22 @@ msgstr "Kibocsátási Maszk"
#: 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
+#, fuzzy
+msgid "Directed Border Pixels"
+msgstr "Könyvtárak és Fájlok:"
+
+#: editor/plugins/cpu_particles_2d_editor_plugin.cpp
+#: editor/plugins/particles_2d_editor_plugin.cpp
msgid "Capture from Pixel"
msgstr "Kinyerés Pixelből"
@@ -9847,6 +9875,10 @@ msgid "Export PCK/Zip"
msgstr ""
#: editor/project_export.cpp
+msgid "Export Project"
+msgstr "Projekt Exportálása"
+
+#: editor/project_export.cpp
#, fuzzy
msgid "Export mode?"
msgstr "Projekt Exportálása"
@@ -9940,10 +9972,6 @@ msgid "Couldn't create project.godot in project path."
msgstr ""
#: editor/project_manager.cpp
-msgid "The following files failed extraction from package:"
-msgstr ""
-
-#: editor/project_manager.cpp
msgid "Rename Project"
msgstr ""
@@ -11159,6 +11187,11 @@ msgstr "Meglévő Busz Elrendezés betöltése."
#: editor/script_create_dialog.cpp
#, fuzzy
+msgid "Script file already exists."
+msgstr "Már létezik '%s' AutoLoad!"
+
+#: editor/script_create_dialog.cpp
+#, fuzzy
msgid "Class Name:"
msgstr "Osztály:"
@@ -12750,7 +12783,14 @@ msgid "This node has been deprecated. Use AnimationTree instead."
msgstr ""
#: scene/gui/color_picker.cpp
-msgid "Pick a color from the screen."
+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
@@ -12861,6 +12901,12 @@ msgstr ""
msgid "Constants cannot be modified."
msgstr ""
+#~ msgid "Project export failed with error code %d."
+#~ msgstr "Projekt export nem sikerült, hibakód %d."
+
+#~ msgid "Password:"
+#~ msgstr "Jelszó:"
+
#~ msgid "Pause the scene"
#~ msgstr "Szünetelteti a jelenetet"
@@ -13044,10 +13090,6 @@ msgstr ""
#~ msgstr "Oszlop:"
#, fuzzy
-#~ msgid "Split already exists."
-#~ msgstr "Már létezik '%s' AutoLoad!"
-
-#, fuzzy
#~ msgid "Add Split"
#~ msgstr "Pont hozzáadása"
diff --git a/editor/translations/id.po b/editor/translations/id.po
index 6024727388..73e51a5cab 100644
--- a/editor/translations/id.po
+++ b/editor/translations/id.po
@@ -1209,10 +1209,24 @@ msgid "Error opening package file, not in ZIP format."
msgstr "Gagal saat membuka paket, tidak dalam bentuk zip."
#: editor/editor_asset_installer.cpp
+#, fuzzy
+msgid "%s (Already Exists)"
+msgstr "Autoload '%s' telah ada!"
+
+#: editor/editor_asset_installer.cpp
msgid "Uncompressing Assets"
msgstr "Membuka Aset Terkompresi"
#: editor/editor_asset_installer.cpp editor/project_manager.cpp
+msgid "The following files failed extraction from package:"
+msgstr "Berkas berikut gagal diekstrak dari paket:"
+
+#: editor/editor_asset_installer.cpp
+#, fuzzy
+msgid "And %s more files."
+msgstr "%d file lagi"
+
+#: editor/editor_asset_installer.cpp editor/project_manager.cpp
msgid "Package installed successfully!"
msgstr "Paket Sukses Terpasang!"
@@ -1221,6 +1235,11 @@ msgstr "Paket Sukses Terpasang!"
msgid "Success!"
msgstr "Sukses!"
+#: editor/editor_asset_installer.cpp
+#, fuzzy
+msgid "Package Contents:"
+msgstr "Konten:"
+
#: editor/editor_asset_installer.cpp editor/editor_node.cpp
msgid "Install"
msgstr "Pasang"
@@ -1359,6 +1378,11 @@ msgid "Invalid file, not an audio bus layout."
msgstr "Berkas salah, tidak layout suara bus."
#: editor/editor_audio_buses.cpp
+#, fuzzy
+msgid "Error saving file: %s"
+msgstr "Galat saat menyimpan berkas!"
+
+#: editor/editor_audio_buses.cpp
msgid "Add Bus"
msgstr "Tambahkan Bus"
@@ -2155,10 +2179,6 @@ msgid "New Window"
msgstr "Jendela Baru"
#: editor/editor_node.cpp
-msgid "Project export failed with error code %d."
-msgstr "Ekspor proyek gagal dengan kode kesalahan %d."
-
-#: editor/editor_node.cpp
msgid "Imported resources can't be saved."
msgstr "Sumber daya yang diimpor tidak dapat disimpan."
@@ -3075,10 +3095,6 @@ msgstr "Impor Templat dari Berkas ZIP"
msgid "Template Package"
msgstr "Manajer Templat Ekspor"
-#: editor/editor_node.cpp editor/project_export.cpp
-msgid "Export Project"
-msgstr "Ekspor Projek"
-
#: editor/editor_node.cpp
msgid "Export Library"
msgstr "Ekspor Pustaka"
@@ -3088,10 +3104,6 @@ msgid "Merge With Existing"
msgstr "Gabung dengan yang Ada"
#: editor/editor_node.cpp
-msgid "Password:"
-msgstr "Sandi:"
-
-#: editor/editor_node.cpp
msgid "Open & Run a Script"
msgstr "Buka & Jalankan Skrip"
@@ -5744,6 +5756,23 @@ msgstr "Masker Emisi"
#: editor/plugins/cpu_particles_2d_editor_plugin.cpp
#: editor/plugins/particles_2d_editor_plugin.cpp
+#, fuzzy
+msgid "Solid Pixels"
+msgstr "Pertumbuhan (Piksel): "
+
+#: 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
+#, fuzzy
+msgid "Directed Border Pixels"
+msgstr "Direktori-direktori & File-file:"
+
+#: editor/plugins/cpu_particles_2d_editor_plugin.cpp
+#: editor/plugins/particles_2d_editor_plugin.cpp
msgid "Capture from Pixel"
msgstr "Tangkap dari Piksel"
@@ -9516,6 +9545,10 @@ msgid "Export PCK/Zip"
msgstr "Ekspor PCK/Zip"
#: editor/project_export.cpp
+msgid "Export Project"
+msgstr "Ekspor Projek"
+
+#: editor/project_export.cpp
msgid "Export mode?"
msgstr "Mode ekspor?"
@@ -9609,10 +9642,6 @@ msgid "Couldn't create project.godot in project path."
msgstr "Tidak dapat membuat project.godot dalam lokasi proyek."
#: editor/project_manager.cpp
-msgid "The following files failed extraction from package:"
-msgstr "Berkas berikut gagal diekstrak dari paket:"
-
-#: editor/project_manager.cpp
msgid "Rename Project"
msgstr "Ubah Nama Proyek"
@@ -10831,6 +10860,11 @@ msgstr "Akan memuat berkas skrip yang ada."
#: editor/script_create_dialog.cpp
#, fuzzy
+msgid "Script file already exists."
+msgstr "Autoload '%s' telah ada!"
+
+#: editor/script_create_dialog.cpp
+#, fuzzy
msgid "Class Name:"
msgstr "Nama Kelas"
@@ -12508,7 +12542,15 @@ msgid "This node has been deprecated. Use AnimationTree instead."
msgstr "Node ini telah usang. Gunakan AnimationTree sebagai gantinya."
#: scene/gui/color_picker.cpp
-msgid "Pick a color from the screen."
+msgid ""
+"Color: #%s\n"
+"LMB: Set color\n"
+"RMB: Remove preset"
+msgstr ""
+
+#: scene/gui/color_picker.cpp
+#, fuzzy
+msgid "Pick a color from the editor window."
msgstr "Ambil warna dari layar."
#: scene/gui/color_picker.cpp
@@ -12636,6 +12678,12 @@ msgstr "Variasi hanya bisa ditetapkan dalam fungsi vertex."
msgid "Constants cannot be modified."
msgstr "Konstanta tidak dapat dimodifikasi."
+#~ msgid "Project export failed with error code %d."
+#~ msgstr "Ekspor proyek gagal dengan kode kesalahan %d."
+
+#~ msgid "Password:"
+#~ msgstr "Sandi:"
+
#~ msgid "Pause the scene"
#~ msgstr "Hentikan sementara skena ini"
@@ -12916,10 +12964,6 @@ msgstr "Konstanta tidak dapat dimodifikasi."
#~ "node Path2D."
#, fuzzy
-#~ msgid "Split already exists."
-#~ msgstr "Autoload '%s' telah ada!"
-
-#, fuzzy
#~ msgid "Add Split"
#~ msgstr "Tambahkan Sinyal"
diff --git a/editor/translations/is.po b/editor/translations/is.po
index 372960230e..5d3445d1c5 100644
--- a/editor/translations/is.po
+++ b/editor/translations/is.po
@@ -1190,10 +1190,22 @@ msgid "Error opening package file, not in ZIP format."
msgstr ""
#: editor/editor_asset_installer.cpp
+msgid "%s (Already Exists)"
+msgstr ""
+
+#: editor/editor_asset_installer.cpp
msgid "Uncompressing Assets"
msgstr ""
#: editor/editor_asset_installer.cpp editor/project_manager.cpp
+msgid "The following files failed extraction from package:"
+msgstr ""
+
+#: editor/editor_asset_installer.cpp
+msgid "And %s more files."
+msgstr ""
+
+#: editor/editor_asset_installer.cpp editor/project_manager.cpp
msgid "Package installed successfully!"
msgstr ""
@@ -1202,6 +1214,10 @@ msgstr ""
msgid "Success!"
msgstr ""
+#: editor/editor_asset_installer.cpp
+msgid "Package Contents:"
+msgstr ""
+
#: editor/editor_asset_installer.cpp editor/editor_node.cpp
msgid "Install"
msgstr ""
@@ -1340,6 +1356,10 @@ msgid "Invalid file, not an audio bus layout."
msgstr ""
#: editor/editor_audio_buses.cpp
+msgid "Error saving file: %s"
+msgstr ""
+
+#: editor/editor_audio_buses.cpp
msgid "Add Bus"
msgstr ""
@@ -2116,10 +2136,6 @@ msgid "New Window"
msgstr ""
#: editor/editor_node.cpp
-msgid "Project export failed with error code %d."
-msgstr ""
-
-#: editor/editor_node.cpp
msgid "Imported resources can't be saved."
msgstr ""
@@ -2963,10 +2979,6 @@ msgstr ""
msgid "Template Package"
msgstr ""
-#: editor/editor_node.cpp editor/project_export.cpp
-msgid "Export Project"
-msgstr ""
-
#: editor/editor_node.cpp
msgid "Export Library"
msgstr ""
@@ -2976,10 +2988,6 @@ msgid "Merge With Existing"
msgstr ""
#: editor/editor_node.cpp
-msgid "Password:"
-msgstr ""
-
-#: editor/editor_node.cpp
msgid "Open & Run a Script"
msgstr ""
@@ -5566,6 +5574,21 @@ 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 ""
@@ -9228,6 +9251,10 @@ msgid "Export PCK/Zip"
msgstr ""
#: editor/project_export.cpp
+msgid "Export Project"
+msgstr ""
+
+#: editor/project_export.cpp
msgid "Export mode?"
msgstr ""
@@ -9318,10 +9345,6 @@ msgid "Couldn't create project.godot in project path."
msgstr ""
#: editor/project_manager.cpp
-msgid "The following files failed extraction from package:"
-msgstr ""
-
-#: editor/project_manager.cpp
msgid "Rename Project"
msgstr ""
@@ -10491,6 +10514,10 @@ msgid "Will load an existing script file."
msgstr ""
#: editor/script_create_dialog.cpp
+msgid "Script file already exists."
+msgstr ""
+
+#: editor/script_create_dialog.cpp
msgid "Class Name:"
msgstr ""
@@ -12030,7 +12057,14 @@ msgid "This node has been deprecated. Use AnimationTree instead."
msgstr ""
#: scene/gui/color_picker.cpp
-msgid "Pick a color from the screen."
+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
diff --git a/editor/translations/it.po b/editor/translations/it.po
index 054b292c45..deb6a489ef 100644
--- a/editor/translations/it.po
+++ b/editor/translations/it.po
@@ -1229,10 +1229,24 @@ msgid "Error opening package file, not in ZIP format."
msgstr "Errore nell'apertura del file package: non è in formato ZIP."
#: editor/editor_asset_installer.cpp
+#, fuzzy
+msgid "%s (Already Exists)"
+msgstr "Già esistente"
+
+#: editor/editor_asset_installer.cpp
msgid "Uncompressing Assets"
msgstr "Estrazione asset"
#: editor/editor_asset_installer.cpp editor/project_manager.cpp
+msgid "The following files failed extraction from package:"
+msgstr "Impossibile estrarre i file seguenti dal pacchetto:"
+
+#: editor/editor_asset_installer.cpp
+#, fuzzy
+msgid "And %s more files."
+msgstr "%d altri file"
+
+#: editor/editor_asset_installer.cpp editor/project_manager.cpp
msgid "Package installed successfully!"
msgstr "Pacchetto installato con successo!"
@@ -1241,6 +1255,11 @@ msgstr "Pacchetto installato con successo!"
msgid "Success!"
msgstr "Successo!"
+#: editor/editor_asset_installer.cpp
+#, fuzzy
+msgid "Package Contents:"
+msgstr "Contenuti:"
+
#: editor/editor_asset_installer.cpp editor/editor_node.cpp
msgid "Install"
msgstr "Installa"
@@ -1379,6 +1398,11 @@ msgid "Invalid file, not an audio bus layout."
msgstr "File non valido, non è una disposizione di un bus audio."
#: editor/editor_audio_buses.cpp
+#, fuzzy
+msgid "Error saving file: %s"
+msgstr "Errore nel salvataggio file!"
+
+#: editor/editor_audio_buses.cpp
msgid "Add Bus"
msgstr "Aggiungi bus"
@@ -2177,10 +2201,6 @@ msgid "New Window"
msgstr "Nuova Finestra"
#: editor/editor_node.cpp
-msgid "Project export failed with error code %d."
-msgstr "Esportazione progetto fallita con codice di errore %d."
-
-#: editor/editor_node.cpp
msgid "Imported resources can't be saved."
msgstr "Le risorse importate non possono essere salvate."
@@ -3112,10 +3132,6 @@ msgstr "Importa template da un file ZIP"
msgid "Template Package"
msgstr "Pacchetto Modello"
-#: editor/editor_node.cpp editor/project_export.cpp
-msgid "Export Project"
-msgstr "Esporta progetto"
-
#: editor/editor_node.cpp
msgid "Export Library"
msgstr "Esporta libreria"
@@ -3125,10 +3141,6 @@ msgid "Merge With Existing"
msgstr "Unisci con esistente"
#: editor/editor_node.cpp
-msgid "Password:"
-msgstr "Password:"
-
-#: editor/editor_node.cpp
msgid "Open & Run a Script"
msgstr "Apri ed esegui uno script"
@@ -5769,6 +5781,23 @@ msgstr "Maschera Emissione"
#: editor/plugins/cpu_particles_2d_editor_plugin.cpp
#: editor/plugins/particles_2d_editor_plugin.cpp
+#, fuzzy
+msgid "Solid Pixels"
+msgstr "Rimpicciolisci (Pixels): "
+
+#: 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
+#, fuzzy
+msgid "Directed Border Pixels"
+msgstr "File e cartelle:"
+
+#: editor/plugins/cpu_particles_2d_editor_plugin.cpp
+#: editor/plugins/particles_2d_editor_plugin.cpp
msgid "Capture from Pixel"
msgstr "Cattura da Pixel"
@@ -9530,6 +9559,10 @@ msgid "Export PCK/Zip"
msgstr "Esporta PCK/Zip"
#: editor/project_export.cpp
+msgid "Export Project"
+msgstr "Esporta progetto"
+
+#: editor/project_export.cpp
msgid "Export mode?"
msgstr "Modalità di esportazione?"
@@ -9623,10 +9656,6 @@ msgid "Couldn't create project.godot in project path."
msgstr "Impossibile creare project.godot nel percorso di progetto."
#: editor/project_manager.cpp
-msgid "The following files failed extraction from package:"
-msgstr "Impossibile estrarre i file seguenti dal pacchetto:"
-
-#: editor/project_manager.cpp
msgid "Rename Project"
msgstr "Rinomina progetto"
@@ -10866,6 +10895,11 @@ msgid "Will load an existing script file."
msgstr "Caricherà un file di script esistente."
#: editor/script_create_dialog.cpp
+#, fuzzy
+msgid "Script file already exists."
+msgstr "L'Azione '%s' esiste già!"
+
+#: editor/script_create_dialog.cpp
msgid "Class Name:"
msgstr "Nome Classe:"
@@ -12558,7 +12592,15 @@ msgid "This node has been deprecated. Use AnimationTree instead."
msgstr "Questo nodo è stato deprecato. In alternativa, usa un AnimationTree."
#: scene/gui/color_picker.cpp
-msgid "Pick a color from the screen."
+msgid ""
+"Color: #%s\n"
+"LMB: Set color\n"
+"RMB: Remove preset"
+msgstr ""
+
+#: scene/gui/color_picker.cpp
+#, fuzzy
+msgid "Pick a color from the editor window."
msgstr "Scegliere un colore dallo schermo."
#: scene/gui/color_picker.cpp
@@ -12679,6 +12721,12 @@ msgstr "Varyings può essere assegnato soltanto nella funzione del vertice."
msgid "Constants cannot be modified."
msgstr "Le constanti non possono essere modificate."
+#~ msgid "Project export failed with error code %d."
+#~ msgstr "Esportazione progetto fallita con codice di errore %d."
+
+#~ msgid "Password:"
+#~ msgstr "Password:"
+
#~ msgid "Identifier segments must be of non-zero length."
#~ msgstr ""
#~ "I segmenti identificativi devono essere di lunghezza diversa da zero."
@@ -12977,9 +13025,6 @@ msgstr "Le constanti non possono essere modificate."
#~ msgid "Create folder"
#~ msgstr "Crea Cartella"
-#~ msgid "Already existing"
-#~ msgstr "Già esistente"
-
#~ msgid "Custom Node"
#~ msgstr "Nodo Personalizzato"
@@ -13026,10 +13071,6 @@ msgstr "Le constanti non possono essere modificate."
#~ "Path2D."
#, fuzzy
-#~ msgid "Split already exists."
-#~ msgstr "L'Azione '%s' esiste già!"
-
-#, fuzzy
#~ msgid "Add Split"
#~ msgstr "Aggiungi punto"
diff --git a/editor/translations/ja.po b/editor/translations/ja.po
index ad11474725..88a9cefed7 100644
--- a/editor/translations/ja.po
+++ b/editor/translations/ja.po
@@ -28,13 +28,15 @@
# leela <53352@protonmail.com>, 2019.
# Tarou Yamada <mizuningyou@yahoo.co.jp>, 2019.
# kazuma kondo <kazmax7@gmail.com>, 2019.
-# Akihiro Ogoshi <technical@palsystem-game.com>, 2019.
+# Akihiro Ogoshi <technical@palsystem-game.com>, 2019, 2020.
+# Wataru Onuki <bettawat@yahoo.co.jp>, 2020.
+# sporeball <sporeballdev@gmail.com>, 2020.
msgid ""
msgstr ""
"Project-Id-Version: Godot Engine editor\n"
"POT-Creation-Date: \n"
-"PO-Revision-Date: 2019-12-25 12:45+0000\n"
-"Last-Translator: Akihiro Ogoshi <technical@palsystem-game.com>\n"
+"PO-Revision-Date: 2020-01-12 13:25+0000\n"
+"Last-Translator: sporeball <sporeballdev@gmail.com>\n"
"Language-Team: Japanese <https://hosted.weblate.org/projects/godot-engine/"
"godot/ja/>\n"
"Language: ja\n"
@@ -42,7 +44,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 3.10\n"
+"X-Generator: Weblate 3.10.1\n"
#: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp
#: modules/visual_script/visual_script_builtin_funcs.cpp
@@ -77,7 +79,7 @@ msgstr "基本型 %s ã®åž‹ %s ã®ã‚¤ãƒ³ãƒ‡ãƒƒã‚¯ã‚¹ãŒç„¡åŠ¹ã§ã™"
#: core/math/expression.cpp
msgid "Invalid named index '%s' for base type %s"
-msgstr "インデックス '%s' (%s型)ã¯ç„¡åŠ¹ãªåå‰ã§ã™"
+msgstr "インデックス '%s' (基底型 %s) ã¯ç„¡åŠ¹ãªåå‰ã§ã™"
#: core/math/expression.cpp
msgid "Invalid arguments to construct '%s'"
@@ -446,7 +448,7 @@ msgstr "root ãŒç„¡ã‘ã‚Œã°æ–°è¦ãƒˆãƒ©ãƒƒã‚¯ã¯è¿½åŠ ã§ãã¾ã›ã‚“"
#: editor/animation_track_editor.cpp
msgid "Invalid track for Bezier (no suitable sub-properties)"
-msgstr ""
+msgstr "無効ãªãƒ™ã‚¸ã‚§ãƒˆãƒ©ãƒƒã‚¯ (é©åˆ‡ãªå‰¯ãƒ—ロパティ無ã—)"
#: editor/animation_track_editor.cpp
msgid "Add Bezier Track"
@@ -556,7 +558,7 @@ msgstr "秒"
#: editor/animation_track_editor.cpp
msgid "FPS"
-msgstr "フレームレート"
+msgstr "フレームレート(FPS)"
#: editor/animation_track_editor.cpp editor/editor_properties.cpp
#: editor/plugins/polygon_2d_editor_plugin.cpp
@@ -1215,10 +1217,24 @@ msgid "Error opening package file, not in ZIP format."
msgstr "パッケージファイルを開ã‘ã¾ã›ã‚“ã§ã—ãŸã€zip å½¢å¼ã§ã¯ã‚ã‚Šã¾ã›ã‚“。"
#: editor/editor_asset_installer.cpp
+#, fuzzy
+msgid "%s (Already Exists)"
+msgstr "æ—¢ã«å­˜åœ¨ã—ã¾ã™"
+
+#: editor/editor_asset_installer.cpp
msgid "Uncompressing Assets"
msgstr "アセットを展開"
#: editor/editor_asset_installer.cpp editor/project_manager.cpp
+msgid "The following files failed extraction from package:"
+msgstr "次ã®ãƒ•ã‚¡ã‚¤ãƒ«ã‚’パッケージã‹ã‚‰æŠ½å‡ºã§ãã¾ã›ã‚“ã§ã—ãŸ:"
+
+#: editor/editor_asset_installer.cpp
+#, fuzzy
+msgid "And %s more files."
+msgstr "%d 以上ã®ãƒ•ã‚¡ã‚¤ãƒ«"
+
+#: editor/editor_asset_installer.cpp editor/project_manager.cpp
msgid "Package installed successfully!"
msgstr "パッケージã®ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã«æˆåŠŸã—ã¾ã—ãŸ!"
@@ -1227,6 +1243,11 @@ msgstr "パッケージã®ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã«æˆåŠŸã—ã¾ã—ãŸ!"
msgid "Success!"
msgstr "æˆåŠŸï¼"
+#: editor/editor_asset_installer.cpp
+#, fuzzy
+msgid "Package Contents:"
+msgstr "コンテンツ:"
+
#: editor/editor_asset_installer.cpp editor/editor_node.cpp
msgid "Install"
msgstr "インストール"
@@ -1365,6 +1386,11 @@ msgid "Invalid file, not an audio bus layout."
msgstr "無効ãªãƒ•ã‚¡ã‚¤ãƒ«ã§ã™ã€‚オーディオãƒã‚¹ã®ãƒ¬ã‚¤ã‚¢ã‚¦ãƒˆã§ã¯ã‚ã‚Šã¾ã›ã‚“。"
#: editor/editor_audio_buses.cpp
+#, fuzzy
+msgid "Error saving file: %s"
+msgstr "ファイルã®ä¿å­˜ã‚¨ãƒ©ãƒ¼!"
+
+#: editor/editor_audio_buses.cpp
msgid "Add Bus"
msgstr "ãƒã‚¹ã‚’追加"
@@ -2071,12 +2097,10 @@ msgid "Constant"
msgstr "コンスタント"
#: editor/editor_help_search.cpp
-#, fuzzy
msgid "Property"
-msgstr "プロパティ:"
+msgstr "プロパティ"
#: editor/editor_help_search.cpp
-#, fuzzy
msgid "Theme Property"
msgstr "テーマプロパティ"
@@ -2161,10 +2185,6 @@ msgid "New Window"
msgstr "æ–°è¦ã‚¦ã‚£ãƒ³ãƒ‰ã‚¦"
#: editor/editor_node.cpp
-msgid "Project export failed with error code %d."
-msgstr "プロジェクトã®ã‚¨ã‚¯ã‚¹ãƒãƒ¼ãƒˆãŒã‚¨ãƒ©ãƒ¼ã‚³ãƒ¼ãƒ‰ %d ã§å¤±æ•—ã—ã¾ã—ãŸã€‚"
-
-#: editor/editor_node.cpp
msgid "Imported resources can't be saved."
msgstr "インãƒãƒ¼ãƒˆã—ãŸãƒªã‚½ãƒ¼ã‚¹ã¯ä¿å­˜ã§ãã¾ã›ã‚“。"
@@ -2514,8 +2534,8 @@ msgstr ""
msgid ""
"Unable to load addon script from path: '%s' Base type is not EditorPlugin."
msgstr ""
-"パス '%s' ã‹ã‚‰ã‚¢ãƒ‰ã‚ªãƒ³ã‚¹ã‚¯ãƒªãƒ—トを読込ã‚ã¾ã›ã‚“。基本型ãŒã‚¨ãƒ‡ã‚£ã‚¿ãƒ—ラグインã§"
-"ã¯ã‚ã‚Šã¾ã›ã‚“。"
+"パス '%s' ã‹ã‚‰ã‚¢ãƒ‰ã‚ªãƒ³ã‚¹ã‚¯ãƒªãƒ—トを読込ã‚ã¾ã›ã‚“。基底型㌠EditorPlugin ã§ã¯ã‚"
+"ã‚Šã¾ã›ã‚“。"
#: editor/editor_node.cpp
msgid "Unable to load addon script from path: '%s' Script is not in tool mode."
@@ -3078,10 +3098,6 @@ msgstr "ZIPファイルã‹ã‚‰ãƒ†ãƒ³ãƒ—レートをインãƒãƒ¼ãƒˆ"
msgid "Template Package"
msgstr "テンプレートパッケージ"
-#: editor/editor_node.cpp editor/project_export.cpp
-msgid "Export Project"
-msgstr "プロジェクトã®ã‚¨ã‚¯ã‚¹ãƒãƒ¼ãƒˆ"
-
#: editor/editor_node.cpp
msgid "Export Library"
msgstr "ライブラリã®ã‚¨ã‚¯ã‚¹ãƒãƒ¼ãƒˆ"
@@ -3091,10 +3107,6 @@ msgid "Merge With Existing"
msgstr "既存ã®ï¼ˆãƒ©ã‚¤ãƒ–ラリを)マージ"
#: editor/editor_node.cpp
-msgid "Password:"
-msgstr "パスワード:"
-
-#: editor/editor_node.cpp
msgid "Open & Run a Script"
msgstr "スクリプトを開ã„ã¦å®Ÿè¡Œ"
@@ -3209,7 +3221,7 @@ msgstr "å«"
#: editor/editor_profiler.cpp
msgid "Self"
-msgstr "セルフ"
+msgstr "セルフ(Self)"
#: editor/editor_profiler.cpp
msgid "Frame #:"
@@ -3462,7 +3474,7 @@ msgstr "ç½²åオブジェクトã®ç”Ÿæˆã‚¨ãƒ©ãƒ¼"
#: editor/export_template_manager.cpp
msgid "Error parsing JSON of mirror list. Please report this issue!"
-msgstr ""
+msgstr "ミラーリストã®JSONを読ã¿è¾¼ã¿å¤±æ•—。ã“ã®å•é¡Œã®å ±å‘Šã‚’ãŠé¡˜ã„ã—ã¾ã™ï¼"
#: editor/export_template_manager.cpp
msgid ""
@@ -4991,29 +5003,27 @@ msgstr "ã“ã®ã‚¢ã‚»ãƒƒãƒˆã®ãƒ€ã‚¦ãƒ³ãƒ­ãƒ¼ãƒ‰ã¯æ—¢ã«é€²è¡Œä¸­ï¼"
#: editor/plugins/asset_library_editor_plugin.cpp
msgid "Recently Updated"
-msgstr "最新ã®ã‚¢ãƒƒãƒ—デート"
+msgstr "更新日時"
#: editor/plugins/asset_library_editor_plugin.cpp
msgid "Least Recently Updated"
-msgstr ""
+msgstr "更新日時 (逆)"
#: editor/plugins/asset_library_editor_plugin.cpp
msgid "Name (A-Z)"
-msgstr ""
+msgstr "åå‰ (Aã‹ã‚‰Z)"
#: editor/plugins/asset_library_editor_plugin.cpp
msgid "Name (Z-A)"
-msgstr ""
+msgstr "åå‰ (Zã‹ã‚‰A)"
#: editor/plugins/asset_library_editor_plugin.cpp
-#, fuzzy
msgid "License (A-Z)"
-msgstr "ライセンス"
+msgstr "ライセンス (Aã‹ã‚‰Z)"
#: editor/plugins/asset_library_editor_plugin.cpp
-#, fuzzy
msgid "License (Z-A)"
-msgstr "ライセンス"
+msgstr "ライセンス (Zã‹ã‚‰A)"
#: editor/plugins/asset_library_editor_plugin.cpp
msgid "First"
@@ -5130,9 +5140,8 @@ msgid "Primary Line Every:"
msgstr ""
#: editor/plugins/canvas_item_editor_plugin.cpp
-#, fuzzy
msgid "steps"
-msgstr "2ステップ"
+msgstr "ステップ"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Rotation Offset:"
@@ -5254,36 +5263,32 @@ msgid "Center"
msgstr "中央"
#: editor/plugins/canvas_item_editor_plugin.cpp
-#, fuzzy
msgid "Left Wide"
-msgstr "å·¦å´é¢å›³"
+msgstr "左伸長"
#: editor/plugins/canvas_item_editor_plugin.cpp
-#, fuzzy
msgid "Top Wide"
-msgstr "上é¢å›³"
+msgstr "上伸長"
#: editor/plugins/canvas_item_editor_plugin.cpp
-#, fuzzy
msgid "Right Wide"
-msgstr "å³å´é¢å›³"
+msgstr "å³ä¼¸é•·"
#: editor/plugins/canvas_item_editor_plugin.cpp
-#, fuzzy
msgid "Bottom Wide"
-msgstr "下é¢å›³"
+msgstr "下伸長"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "VCenter Wide"
-msgstr ""
+msgstr "中央垂直伸長"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "HCenter Wide"
-msgstr ""
+msgstr "中央水平伸長"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Full Rect"
-msgstr ""
+msgstr "Rectå…¨é¢"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Keep Ratio"
@@ -5721,6 +5726,23 @@ msgstr "放出マスク"
#: editor/plugins/cpu_particles_2d_editor_plugin.cpp
#: editor/plugins/particles_2d_editor_plugin.cpp
+#, fuzzy
+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
+#, fuzzy
+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 "ピクセルã‹ã‚‰ã‚­ãƒ£ãƒ—ãƒãƒ£"
@@ -9380,7 +9402,7 @@ msgstr ""
#: editor/project_export.cpp
msgid "Presets"
-msgstr "åˆæœŸè¨­å®šå€¤"
+msgstr "プリセット"
#: editor/project_export.cpp editor/project_settings_editor.cpp
msgid "Add..."
@@ -9391,6 +9413,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 ""
+"ãƒã‚§ãƒƒã‚¯ã‚’入れるã¨ã€ï¼‘クリック・デプロイã§ã‚‚ã“ã®ãƒ—リセットãŒä½¿ã‚れるよã†ã«ãª"
+"ã‚Šã¾ã™ã€‚ã²ã¨ã¤ã®ãƒ—ラットフォームã«å¯¾ã—ã€ã²ã¨ã¤ã®ãƒ—リセットã®ã¿ãŒå®Ÿè¡Œå¯èƒ½ã¨ã—"
+"ã¦ãƒžãƒ¼ã‚¯ã§ãã¾ã™ã€‚"
#: editor/project_export.cpp
msgid "Export Path"
@@ -9493,6 +9518,10 @@ msgid "Export PCK/Zip"
msgstr "PCK/Zipã®ã‚¨ã‚¯ã‚¹ãƒãƒ¼ãƒˆ"
#: editor/project_export.cpp
+msgid "Export Project"
+msgstr "プロジェクトã®ã‚¨ã‚¯ã‚¹ãƒãƒ¼ãƒˆ"
+
+#: editor/project_export.cpp
msgid "Export mode?"
msgstr "エクスãƒãƒ¼ãƒˆ モード?"
@@ -9587,10 +9616,6 @@ msgid "Couldn't create project.godot in project path."
msgstr "project.godot をプロジェクトパスã«ç”Ÿæˆã§ãã¾ã›ã‚“ã§ã—ãŸã€‚"
#: editor/project_manager.cpp
-msgid "The following files failed extraction from package:"
-msgstr "次ã®ãƒ•ã‚¡ã‚¤ãƒ«ã‚’パッケージã‹ã‚‰æŠ½å‡ºã§ãã¾ã›ã‚“ã§ã—ãŸ:"
-
-#: editor/project_manager.cpp
msgid "Rename Project"
msgstr "プロジェクトåã®å¤‰æ›´"
@@ -10100,7 +10125,7 @@ msgstr "アクション:"
#: editor/project_settings_editor.cpp
msgid "Action"
-msgstr "アクション"
+msgstr "アクション(Action)"
#: editor/project_settings_editor.cpp
msgid "Deadzone"
@@ -10826,6 +10851,11 @@ msgid "Will load an existing script file."
msgstr "既存ã®ã‚¹ã‚¯ãƒªãƒ—トファイルを読ã¿è¾¼ã‚€ã€‚"
#: editor/script_create_dialog.cpp
+#, fuzzy
+msgid "Script file already exists."
+msgstr "アクション'%s'ã¯æ—¢ã«ã‚ã‚Šã¾ã™!"
+
+#: editor/script_create_dialog.cpp
msgid "Class Name:"
msgstr "クラスå:"
@@ -10947,7 +10977,7 @@ msgstr "ビデオメモリー"
#: editor/script_editor_debugger.cpp
msgid "Resource Path"
-msgstr "リソースã®ãƒ‘ス"
+msgstr "リソースã®ãƒ‘ス(ResourcePath)"
#: editor/script_editor_debugger.cpp
msgid "Type"
@@ -11136,7 +11166,7 @@ msgstr "ライブラリ: "
#: modules/gdnative/register_types.cpp
msgid "GDNative"
-msgstr "GDNative"
+msgstr "\\ GDNative"
#: modules/gdscript/gdscript_functions.cpp
msgid "Step argument is zero!"
@@ -11585,11 +11615,11 @@ msgstr "Getterプロパティを追加"
#: modules/visual_script/visual_script_editor.cpp
msgid "Add Setter Property"
-msgstr "setterプロパティを追加"
+msgstr "Setterプロパティを追加"
#: modules/visual_script/visual_script_editor.cpp
msgid "Change Base Type"
-msgstr "基本ã®åž‹ã‚’変更"
+msgstr "基底型を変更"
#: modules/visual_script/visual_script_editor.cpp
msgid "Move Node(s)"
@@ -11693,9 +11723,8 @@ msgid "Members:"
msgstr "メンãƒãƒ¼:"
#: modules/visual_script/visual_script_editor.cpp
-#, fuzzy
msgid "Change Base Type:"
-msgstr "基本ã®åž‹ã‚’変更"
+msgstr "基底型を変更:"
#: modules/visual_script/visual_script_editor.cpp
#, fuzzy
@@ -12515,7 +12544,15 @@ msgstr ""
"ã“ã®ãƒŽãƒ¼ãƒ‰ã¯éžæŽ¨å¥¨ã«ãªã‚Šã¾ã—ãŸã€‚代ã‚ã‚Šã«AnimationTreeを使用ã—ã¦ãã ã•ã„。"
#: scene/gui/color_picker.cpp
-msgid "Pick a color from the screen."
+msgid ""
+"Color: #%s\n"
+"LMB: Set color\n"
+"RMB: Remove preset"
+msgstr ""
+
+#: scene/gui/color_picker.cpp
+#, fuzzy
+msgid "Pick a color from the editor window."
msgstr "スクリーンã‹ã‚‰è‰²ã‚’é¸æŠžã—ã¦ãã ã•ã„。"
#: scene/gui/color_picker.cpp
@@ -12641,6 +12678,12 @@ msgstr "Varyingã¯é ‚点関数ã«ã®ã¿å‰²ã‚Šå½“ã¦ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚"
msgid "Constants cannot be modified."
msgstr "定数ã¯å¤‰æ›´ã§ãã¾ã›ã‚“。"
+#~ msgid "Project export failed with error code %d."
+#~ msgstr "プロジェクトã®ã‚¨ã‚¯ã‚¹ãƒãƒ¼ãƒˆãŒã‚¨ãƒ©ãƒ¼ã‚³ãƒ¼ãƒ‰ %d ã§å¤±æ•—ã—ã¾ã—ãŸã€‚"
+
+#~ msgid "Password:"
+#~ msgstr "パスワード:"
+
#~ msgid "Identifier segments must be of non-zero length."
#~ msgstr "識別å­ã‚»ã‚°ãƒ¡ãƒ³ãƒˆã¯ã‚¼ãƒ­ä»¥å¤–ã®é•·ã•ã§ãªã‘ã‚Œã°ãªã‚Šã¾ã›ã‚“。"
@@ -12945,9 +12988,6 @@ msgstr "定数ã¯å¤‰æ›´ã§ãã¾ã›ã‚“。"
#~ msgid "Create folder"
#~ msgstr "フォルダを作æˆ"
-#~ msgid "Already existing"
-#~ msgstr "æ—¢ã«å­˜åœ¨ã—ã¾ã™"
-
#~ msgid "Custom Node"
#~ msgstr "カスタムノード"
@@ -12995,10 +13035,6 @@ msgstr "定数ã¯å¤‰æ›´ã§ãã¾ã›ã‚“。"
#~ msgstr ""
#~ "PathFollow2D ã¯ã€Path2D ノードã®å­ã¨ã—ã¦è¨­å®šã•ã‚Œã¦ã„ã‚‹å ´åˆã®ã¿å‹•ä½œã—ã¾ã™ã€‚"
-#, fuzzy
-#~ msgid "Split already exists."
-#~ msgstr "アクション'%s'ã¯æ—¢ã«ã‚ã‚Šã¾ã™!"
-
#~ msgid "Add Split"
#~ msgstr "分割を追加"
diff --git a/editor/translations/ka.po b/editor/translations/ka.po
index 2c93b4dab9..e937cd3daa 100644
--- a/editor/translations/ka.po
+++ b/editor/translations/ka.po
@@ -1239,10 +1239,22 @@ msgid "Error opening package file, not in ZIP format."
msgstr "შეცდáƒáƒ›áƒ პáƒáƒ™áƒ”ტის გáƒáƒ®áƒ¡áƒœáƒ˜áƒ¡áƒáƒ¡, უნდრიყáƒáƒ¡ zip ფáƒáƒ áƒ›áƒáƒ¢áƒ¨áƒ˜."
#: editor/editor_asset_installer.cpp
+msgid "%s (Already Exists)"
+msgstr ""
+
+#: editor/editor_asset_installer.cpp
msgid "Uncompressing Assets"
msgstr "áƒáƒ¥áƒ¢áƒ˜áƒ•áƒ”ბის áƒáƒ áƒáƒ™áƒáƒ›áƒžáƒ áƒ”სირებáƒ"
#: editor/editor_asset_installer.cpp editor/project_manager.cpp
+msgid "The following files failed extraction from package:"
+msgstr ""
+
+#: editor/editor_asset_installer.cpp
+msgid "And %s more files."
+msgstr ""
+
+#: editor/editor_asset_installer.cpp editor/project_manager.cpp
#, fuzzy
msgid "Package installed successfully!"
msgstr "პáƒáƒ™áƒ”ტი დáƒáƒ§áƒ”ნდრწáƒáƒ áƒ›áƒáƒ¢áƒ”ბით!"
@@ -1252,6 +1264,11 @@ msgstr "პáƒáƒ™áƒ”ტი დáƒáƒ§áƒ”ნდრწáƒáƒ áƒ›áƒáƒ¢áƒ”ბით!
msgid "Success!"
msgstr "წáƒáƒ áƒ›áƒáƒ¢áƒ”ბáƒ!"
+#: editor/editor_asset_installer.cpp
+#, fuzzy
+msgid "Package Contents:"
+msgstr "პáƒáƒ™áƒ”ტების დáƒáƒ›áƒ§áƒ”ნებელი"
+
#: editor/editor_asset_installer.cpp editor/editor_node.cpp
msgid "Install"
msgstr "დáƒáƒ§áƒ”ნებáƒ"
@@ -1391,6 +1408,11 @@ msgid "Invalid file, not an audio bus layout."
msgstr ""
#: editor/editor_audio_buses.cpp
+#, fuzzy
+msgid "Error saving file: %s"
+msgstr "ჩáƒáƒ¢áƒ•áƒ˜áƒ áƒ—ვის შეცდáƒáƒ›áƒ”ბი!"
+
+#: editor/editor_audio_buses.cpp
msgid "Add Bus"
msgstr ""
@@ -2190,10 +2212,6 @@ msgid "New Window"
msgstr ""
#: editor/editor_node.cpp
-msgid "Project export failed with error code %d."
-msgstr ""
-
-#: editor/editor_node.cpp
msgid "Imported resources can't be saved."
msgstr ""
@@ -3042,10 +3060,6 @@ msgstr ""
msgid "Template Package"
msgstr ""
-#: editor/editor_node.cpp editor/project_export.cpp
-msgid "Export Project"
-msgstr ""
-
#: editor/editor_node.cpp
msgid "Export Library"
msgstr ""
@@ -3055,10 +3069,6 @@ msgid "Merge With Existing"
msgstr ""
#: editor/editor_node.cpp
-msgid "Password:"
-msgstr ""
-
-#: editor/editor_node.cpp
msgid "Open & Run a Script"
msgstr ""
@@ -5698,6 +5708,21 @@ 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 ""
@@ -9423,6 +9448,10 @@ msgid "Export PCK/Zip"
msgstr ""
#: editor/project_export.cpp
+msgid "Export Project"
+msgstr ""
+
+#: editor/project_export.cpp
msgid "Export mode?"
msgstr ""
@@ -9513,10 +9542,6 @@ msgid "Couldn't create project.godot in project path."
msgstr ""
#: editor/project_manager.cpp
-msgid "The following files failed extraction from package:"
-msgstr ""
-
-#: editor/project_manager.cpp
msgid "Rename Project"
msgstr ""
@@ -10698,6 +10723,10 @@ msgid "Will load an existing script file."
msgstr ""
#: editor/script_create_dialog.cpp
+msgid "Script file already exists."
+msgstr ""
+
+#: editor/script_create_dialog.cpp
msgid "Class Name:"
msgstr ""
@@ -12262,7 +12291,14 @@ msgid "This node has been deprecated. Use AnimationTree instead."
msgstr ""
#: scene/gui/color_picker.cpp
-msgid "Pick a color from the screen."
+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
diff --git a/editor/translations/ko.po b/editor/translations/ko.po
index 261d978bf7..f16f432e28 100644
--- a/editor/translations/ko.po
+++ b/editor/translations/ko.po
@@ -9,7 +9,7 @@
# TheRedPlanet <junmo.moon8@gmail.com>, 2018.
# Xavier Cho <mysticfallband@gmail.com>, 2018.
# 박한얼 (volzhs) <volzhs@gmail.com>, 2016-2018.
-# 송태섭 <xotjq237@gmail.com>, 2018, 2019.
+# 송태섭 <xotjq237@gmail.com>, 2018, 2019, 2020.
# JY <yimjisoo@mailfence.com>, 2018.
# Ch. <ccwpc@hanmail.net>, 2018.
# moolow <copyhyeon@gmail.com>, 2019.
@@ -19,7 +19,7 @@ msgid ""
msgstr ""
"Project-Id-Version: Godot Engine editor\n"
"POT-Creation-Date: \n"
-"PO-Revision-Date: 2019-12-23 17:08+0000\n"
+"PO-Revision-Date: 2020-01-06 14:21+0000\n"
"Last-Translator: 송태섭 <xotjq237@gmail.com>\n"
"Language-Team: Korean <https://hosted.weblate.org/projects/godot-engine/"
"godot/ko/>\n"
@@ -431,7 +431,7 @@ msgstr "루트 ì—†ì´ ìƒˆ íŠ¸ëž™ì„ ì¶”ê°€í•  수 ì—†ìŒ"
#: editor/animation_track_editor.cpp
msgid "Invalid track for Bezier (no suitable sub-properties)"
-msgstr ""
+msgstr "ë² ì§€ì–´ì— ìž˜ëª»ëœ íŠ¸ëž™ (ì ë‹¹í•œ 하위 ì†ì„±ì´ ì—†ìŒ)"
#: editor/animation_track_editor.cpp
msgid "Add Bezier Track"
@@ -994,7 +994,7 @@ msgstr "리소스"
#: editor/dependency_editor.cpp editor/editor_autoload_settings.cpp
#: editor/project_manager.cpp editor/project_settings_editor.cpp
msgid "Path"
-msgstr "경로"
+msgstr "Path(경로)"
#: editor/dependency_editor.cpp
msgid "Dependencies:"
@@ -1195,10 +1195,24 @@ msgid "Error opening package file, not in ZIP format."
msgstr "패키지 파ì¼ì„ 여는 중 오류. ZIP 형ì‹ì´ 아니ì—ìš”."
#: editor/editor_asset_installer.cpp
+#, fuzzy
+msgid "%s (Already Exists)"
+msgstr "ì´ë¯¸ 존재함"
+
+#: editor/editor_asset_installer.cpp
msgid "Uncompressing Assets"
msgstr "애셋 압축 풀기"
#: editor/editor_asset_installer.cpp editor/project_manager.cpp
+msgid "The following files failed extraction from package:"
+msgstr "ë‹¤ìŒ íŒŒì¼ì„ 패키지ì—ì„œ ì¶”ì¶œí•˜ëŠ”ë° ì‹¤íŒ¨í•¨:"
+
+#: editor/editor_asset_installer.cpp
+#, fuzzy
+msgid "And %s more files."
+msgstr "외 %dê°œì˜ íŒŒì¼"
+
+#: editor/editor_asset_installer.cpp editor/project_manager.cpp
msgid "Package installed successfully!"
msgstr "패키지를 성공ì ìœ¼ë¡œ 설치했어요!"
@@ -1207,6 +1221,11 @@ msgstr "패키지를 성공ì ìœ¼ë¡œ 설치했어요!"
msgid "Success!"
msgstr "성공!"
+#: editor/editor_asset_installer.cpp
+#, fuzzy
+msgid "Package Contents:"
+msgstr "ë‚´ìš©:"
+
#: editor/editor_asset_installer.cpp editor/editor_node.cpp
msgid "Install"
msgstr "설치하기"
@@ -1345,6 +1364,11 @@ msgid "Invalid file, not an audio bus layout."
msgstr "ìž˜ëª»ëœ íŒŒì¼. 오디오 버스 ë ˆì´ì•„ì›ƒì´ ì•„ë‹ˆì—ìš”."
#: editor/editor_audio_buses.cpp
+#, fuzzy
+msgid "Error saving file: %s"
+msgstr "íŒŒì¼ ì €ìž¥ 중 오류!"
+
+#: editor/editor_audio_buses.cpp
msgid "Add Bus"
msgstr "버스 추가하기"
@@ -1993,9 +2017,8 @@ msgid "Case Sensitive"
msgstr "ëŒ€ì†Œë¬¸ìž êµ¬ë¶„"
#: editor/editor_help_search.cpp
-#, fuzzy
msgid "Show Hierarchy"
-msgstr "ë„우미 ë³´ì´ê¸°"
+msgstr "계층 구조 ë³´ì´ê¸°"
#: editor/editor_help_search.cpp
msgid "Display All"
@@ -2034,7 +2057,6 @@ msgid "Class"
msgstr "í´ëž˜ìŠ¤"
#: editor/editor_help_search.cpp
-#, fuzzy
msgid "Method"
msgstr "메서드"
@@ -2047,12 +2069,10 @@ msgid "Constant"
msgstr "비선형"
#: editor/editor_help_search.cpp
-#, fuzzy
msgid "Property"
-msgstr "ì†ì„±:"
+msgstr "ì†ì„±"
#: editor/editor_help_search.cpp
-#, fuzzy
msgid "Theme Property"
msgstr "테마 ì†ì„±"
@@ -2137,10 +2157,6 @@ msgid "New Window"
msgstr "새 창"
#: editor/editor_node.cpp
-msgid "Project export failed with error code %d."
-msgstr "프로ì íŠ¸ ë‚´ë³´ë‚´ê¸°ì— ì‹¤íŒ¨í–ˆì–´ìš”. 오류 코드%d."
-
-#: editor/editor_node.cpp
msgid "Imported resources can't be saved."
msgstr "가져온 리소스를 저장할 수 없어요."
@@ -3039,10 +3055,6 @@ msgstr "ZIP 파ì¼ì—ì„œ 템플릿 가져오기"
msgid "Template Package"
msgstr "템플릿 패키지"
-#: editor/editor_node.cpp editor/project_export.cpp
-msgid "Export Project"
-msgstr "프로ì íŠ¸ 내보내기"
-
#: editor/editor_node.cpp
msgid "Export Library"
msgstr "ë¼ì´ë¸ŒëŸ¬ë¦¬ 내보내기"
@@ -3052,10 +3064,6 @@ msgid "Merge With Existing"
msgstr "ê¸°ì¡´ì˜ ê²ƒê³¼ 병합하기"
#: editor/editor_node.cpp
-msgid "Password:"
-msgstr "암호:"
-
-#: editor/editor_node.cpp
msgid "Open & Run a Script"
msgstr "스í¬ë¦½íŠ¸ 열기 & 실행하기"
@@ -3415,13 +3423,12 @@ msgid "Importing:"
msgstr "가져오는 중:"
#: editor/export_template_manager.cpp
-#, fuzzy
msgid "Error getting the list of mirrors."
-msgstr "서명 오브ì íŠ¸ ìƒì„±ì¤‘ ì—러."
+msgstr "미러 목ë¡ì„ 가져오는 중 오류."
#: editor/export_template_manager.cpp
msgid "Error parsing JSON of mirror list. Please report this issue!"
-msgstr ""
+msgstr "미러 목ë¡ì˜ JSON 구문 ë¶„ì„ ì¤‘ 오류. ì´ ë¬¸ì œë¥¼ 신고해주세요!"
#: editor/export_template_manager.cpp
msgid ""
@@ -4601,9 +4608,8 @@ msgid "Move Node"
msgstr "노드 ì´ë™í•˜ê¸°"
#: editor/plugins/animation_state_machine_editor.cpp
-#, fuzzy
msgid "Transition exists!"
-msgstr "전환"
+msgstr "ì „í™˜ì´ ìžˆì–´ìš”!"
#: editor/plugins/animation_state_machine_editor.cpp
msgid "Add Transition"
@@ -5667,6 +5673,23 @@ msgstr "방출 마스í¬"
#: editor/plugins/cpu_particles_2d_editor_plugin.cpp
#: editor/plugins/particles_2d_editor_plugin.cpp
+#, fuzzy
+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
+#, fuzzy
+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 "픽셀ì—ì„œ 캡처"
@@ -5892,18 +5915,19 @@ msgstr "윤곽 í¬ê¸°:"
#: editor/plugins/mesh_instance_editor_plugin.cpp
msgid "UV Channel Debug"
-msgstr ""
+msgstr "UV ì±„ë„ ë””ë²„ê·¸"
#: editor/plugins/mesh_library_editor_plugin.cpp
msgid "Remove item %d?"
msgstr "%dê°œì˜ í•­ëª©ì„ ì‚­ì œí• ê¹Œìš”?"
#: editor/plugins/mesh_library_editor_plugin.cpp
-#, fuzzy
msgid ""
"Update from existing scene?:\n"
"%s"
-msgstr "씬ì—ì„œ ì—…ë°ì´íŠ¸í•˜ê¸°"
+msgstr ""
+"존재하는 씬ì—ì„œ ì—…ë°ì´íŠ¸í• ê¹Œìš”?\n"
+"%s"
#: editor/plugins/mesh_library_editor_plugin.cpp
msgid "Mesh Library"
@@ -6778,7 +6802,7 @@ msgstr "소스"
#: editor/plugins/script_text_editor.cpp
msgid "Target"
-msgstr "대ìƒ"
+msgstr "Target(대ìƒ)"
#: editor/plugins/script_text_editor.cpp
msgid ""
@@ -7451,9 +7475,8 @@ msgid "Create Mesh2D"
msgstr "Mesh2D 만들기"
#: editor/plugins/sprite_editor_plugin.cpp
-#, fuzzy
msgid "Mesh2D Preview"
-msgstr "메시 미리 보기 만들기"
+msgstr "Mesh2D 미리 보기"
#: editor/plugins/sprite_editor_plugin.cpp
msgid "Create Polygon2D"
@@ -7461,25 +7484,23 @@ msgstr "Polygon2D 만들기"
#: editor/plugins/sprite_editor_plugin.cpp
msgid "Polygon2D Preview"
-msgstr ""
+msgstr "Polygon2D 미리 보기"
#: editor/plugins/sprite_editor_plugin.cpp
msgid "Create CollisionPolygon2D"
msgstr "CollisionPolygon2D 만들기"
#: editor/plugins/sprite_editor_plugin.cpp
-#, fuzzy
msgid "CollisionPolygon2D Preview"
-msgstr "CollisionPolygon2D 만들기"
+msgstr "CollisionPolygon2D 미리 보기"
#: editor/plugins/sprite_editor_plugin.cpp
msgid "Create LightOccluder2D"
msgstr "LightOccluder2D 만들기"
#: editor/plugins/sprite_editor_plugin.cpp
-#, fuzzy
msgid "LightOccluder2D Preview"
-msgstr "LightOccluder2D 만들기"
+msgstr "LightOccluder2D 미리 보기"
#: editor/plugins/sprite_editor_plugin.cpp
msgid "Sprite is empty!"
@@ -7558,9 +7579,8 @@ msgid "Add Frame"
msgstr "프레임 추가하기"
#: editor/plugins/sprite_frames_editor_plugin.cpp
-#, fuzzy
msgid "Unable to load images"
-msgstr "ì´ë¯¸ì§€ë¥¼ 로드할 수 ì—†ìŒ:"
+msgstr "ì´ë¯¸ì§€ë¥¼ 불러올 수 ì—†ìŒ"
#: editor/plugins/sprite_frames_editor_plugin.cpp
msgid "ERROR: Couldn't load frame resource!"
@@ -8247,14 +8267,12 @@ msgid "Edit Tile Z Index"
msgstr "íƒ€ì¼ Z ì¸ë±ìŠ¤ 편집하기"
#: editor/plugins/tile_set_editor_plugin.cpp
-#, fuzzy
msgid "Make Convex"
-msgstr "ë³¼ë¡í•œ í´ë¦¬ê³¤ 만들기"
+msgstr "ë³¼ë¡í•˜ê²Œ 만들기"
#: editor/plugins/tile_set_editor_plugin.cpp
-#, fuzzy
msgid "Make Concave"
-msgstr "오목한 í´ë¦¬ê³¤ 만들기"
+msgstr "오목하게 만들기"
#: editor/plugins/tile_set_editor_plugin.cpp
msgid "Create Collision Polygon"
@@ -9382,6 +9400,10 @@ msgid "Export PCK/Zip"
msgstr "PCK/Zip 내보내기"
#: editor/project_export.cpp
+msgid "Export Project"
+msgstr "프로ì íŠ¸ 내보내기"
+
+#: editor/project_export.cpp
msgid "Export mode?"
msgstr "내보내기 모드?"
@@ -9475,10 +9497,6 @@ msgid "Couldn't create project.godot in project path."
msgstr "프로ì íŠ¸ 경로ì—ì„œ project.godot 파ì¼ì„ ìƒì„±í•  수 없어요."
#: editor/project_manager.cpp
-msgid "The following files failed extraction from package:"
-msgstr "ë‹¤ìŒ íŒŒì¼ì„ 패키지ì—ì„œ ì¶”ì¶œí•˜ëŠ”ë° ì‹¤íŒ¨í•¨:"
-
-#: editor/project_manager.cpp
msgid "Rename Project"
msgstr "프로ì íŠ¸ ì´ë¦„ 바꾸기"
@@ -10700,6 +10718,11 @@ msgid "Will load an existing script file."
msgstr "기존 스í¬ë¦½íŠ¸ 파ì¼ì„ 불러와요."
#: editor/script_create_dialog.cpp
+#, fuzzy
+msgid "Script file already exists."
+msgstr "ì´ë¯¸ 분할ë˜ì—ˆìŠµë‹ˆë‹¤."
+
+#: editor/script_create_dialog.cpp
msgid "Class Name:"
msgstr "í´ëž˜ìŠ¤ ì´ë¦„:"
@@ -11148,9 +11171,8 @@ msgid "Cursor Clear Rotation"
msgstr "커서 회전 지우기"
#: modules/gridmap/grid_map_editor_plugin.cpp
-#, fuzzy
msgid "Paste Selects"
-msgstr "ì„ íƒ ì§€ìš°ê¸°"
+msgstr "ì„ íƒ í•­ëª© 붙여넣기"
#: modules/gridmap/grid_map_editor_plugin.cpp
msgid "Clear Selection"
@@ -12334,7 +12356,15 @@ msgid "This node has been deprecated. Use AnimationTree instead."
msgstr "ì´ ë…¸ë“œëŠ” ë” ì´ìƒ 사용할 수 없어요. 대신 AnimationTree를 사용하세요."
#: scene/gui/color_picker.cpp
-msgid "Pick a color from the screen."
+msgid ""
+"Color: #%s\n"
+"LMB: Set color\n"
+"RMB: Remove preset"
+msgstr ""
+
+#: scene/gui/color_picker.cpp
+#, fuzzy
+msgid "Pick a color from the editor window."
msgstr "화면ì—ì„œ 색ìƒì„ ì„ íƒí•˜ì„¸ìš”."
#: scene/gui/color_picker.cpp
@@ -12453,6 +12483,12 @@ msgstr "Varyingì€ ê¼­ì§“ì  í•¨ìˆ˜ì—만 지정할 수 있어요."
msgid "Constants cannot be modified."
msgstr "ìƒìˆ˜ëŠ” 수정할 수 없어요."
+#~ msgid "Project export failed with error code %d."
+#~ msgstr "프로ì íŠ¸ ë‚´ë³´ë‚´ê¸°ì— ì‹¤íŒ¨í–ˆì–´ìš”. 오류 코드%d."
+
+#~ msgid "Password:"
+#~ msgstr "암호:"
+
#~ msgid "Identifier segments must be of non-zero length."
#~ msgstr "ì‹ë³„ìž ì„¸ê·¸ë¨¼íŠ¸ëŠ” 길ì´ê°€ 0ì´ ì•„ë‹ˆì–´ì•¼ í•´ìš”."
@@ -12911,9 +12947,6 @@ msgstr "ìƒìˆ˜ëŠ” 수정할 수 없어요."
#~ msgid "Create folder"
#~ msgstr "í´ë” 만들기"
-#~ msgid "Already existing"
-#~ msgstr "ì´ë¯¸ 존재함"
-
#~ msgid "Custom Node"
#~ msgstr "커스텀 노드"
@@ -12962,9 +12995,6 @@ msgstr "ìƒìˆ˜ëŠ” 수정할 수 없어요."
#~ msgid "Split can't form an existing edge."
#~ msgstr "ë¶„í• ì€ ì¡´ìž¬í•˜ëŠ” 모서리를 형성할 수 없습니다."
-#~ msgid "Split already exists."
-#~ msgstr "ì´ë¯¸ 분할ë˜ì—ˆìŠµë‹ˆë‹¤."
-
#~ msgid "Add Split"
#~ msgstr "분할 추가"
diff --git a/editor/translations/lt.po b/editor/translations/lt.po
index b202cd2beb..c9de0179b1 100644
--- a/editor/translations/lt.po
+++ b/editor/translations/lt.po
@@ -1205,10 +1205,22 @@ msgid "Error opening package file, not in ZIP format."
msgstr ""
#: editor/editor_asset_installer.cpp
+msgid "%s (Already Exists)"
+msgstr ""
+
+#: editor/editor_asset_installer.cpp
msgid "Uncompressing Assets"
msgstr ""
#: editor/editor_asset_installer.cpp editor/project_manager.cpp
+msgid "The following files failed extraction from package:"
+msgstr ""
+
+#: editor/editor_asset_installer.cpp
+msgid "And %s more files."
+msgstr ""
+
+#: editor/editor_asset_installer.cpp editor/project_manager.cpp
msgid "Package installed successfully!"
msgstr ""
@@ -1217,6 +1229,10 @@ msgstr ""
msgid "Success!"
msgstr ""
+#: editor/editor_asset_installer.cpp
+msgid "Package Contents:"
+msgstr ""
+
#: editor/editor_asset_installer.cpp editor/editor_node.cpp
msgid "Install"
msgstr ""
@@ -1355,6 +1371,11 @@ msgid "Invalid file, not an audio bus layout."
msgstr ""
#: editor/editor_audio_buses.cpp
+#, fuzzy
+msgid "Error saving file: %s"
+msgstr "Įvyko klaida kraunant šriftą."
+
+#: editor/editor_audio_buses.cpp
msgid "Add Bus"
msgstr ""
@@ -2156,10 +2177,6 @@ msgid "New Window"
msgstr ""
#: editor/editor_node.cpp
-msgid "Project export failed with error code %d."
-msgstr ""
-
-#: editor/editor_node.cpp
msgid "Imported resources can't be saved."
msgstr ""
@@ -3007,10 +3024,6 @@ msgstr ""
msgid "Template Package"
msgstr ""
-#: editor/editor_node.cpp editor/project_export.cpp
-msgid "Export Project"
-msgstr ""
-
#: editor/editor_node.cpp
msgid "Export Library"
msgstr ""
@@ -3020,10 +3033,6 @@ msgid "Merge With Existing"
msgstr ""
#: editor/editor_node.cpp
-msgid "Password:"
-msgstr ""
-
-#: editor/editor_node.cpp
msgid "Open & Run a Script"
msgstr ""
@@ -5675,6 +5684,21 @@ 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 ""
@@ -9407,6 +9431,10 @@ msgid "Export PCK/Zip"
msgstr ""
#: editor/project_export.cpp
+msgid "Export Project"
+msgstr ""
+
+#: editor/project_export.cpp
#, fuzzy
msgid "Export mode?"
msgstr "Importuoti iš Nodo:"
@@ -9499,10 +9527,6 @@ msgid "Couldn't create project.godot in project path."
msgstr ""
#: editor/project_manager.cpp
-msgid "The following files failed extraction from package:"
-msgstr ""
-
-#: editor/project_manager.cpp
msgid "Rename Project"
msgstr ""
@@ -10684,6 +10708,10 @@ msgid "Will load an existing script file."
msgstr ""
#: editor/script_create_dialog.cpp
+msgid "Script file already exists."
+msgstr ""
+
+#: editor/script_create_dialog.cpp
#, fuzzy
msgid "Class Name:"
msgstr "Priedai"
@@ -12250,7 +12278,14 @@ msgid "This node has been deprecated. Use AnimationTree instead."
msgstr ""
#: scene/gui/color_picker.cpp
-msgid "Pick a color from the screen."
+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
diff --git a/editor/translations/lv.po b/editor/translations/lv.po
index 05a0656c15..63da6e5725 100644
--- a/editor/translations/lv.po
+++ b/editor/translations/lv.po
@@ -1204,10 +1204,22 @@ msgid "Error opening package file, not in ZIP format."
msgstr "Kļūme atverot arhÄ«vu failu, nav ZIP formÄtÄ."
#: editor/editor_asset_installer.cpp
+msgid "%s (Already Exists)"
+msgstr ""
+
+#: editor/editor_asset_installer.cpp
msgid "Uncompressing Assets"
msgstr ""
#: editor/editor_asset_installer.cpp editor/project_manager.cpp
+msgid "The following files failed extraction from package:"
+msgstr ""
+
+#: editor/editor_asset_installer.cpp
+msgid "And %s more files."
+msgstr ""
+
+#: editor/editor_asset_installer.cpp editor/project_manager.cpp
msgid "Package installed successfully!"
msgstr ""
@@ -1216,6 +1228,10 @@ msgstr ""
msgid "Success!"
msgstr "IzdevÄs!"
+#: editor/editor_asset_installer.cpp
+msgid "Package Contents:"
+msgstr ""
+
#: editor/editor_asset_installer.cpp editor/editor_node.cpp
msgid "Install"
msgstr "Ieinstalēt"
@@ -1354,6 +1370,11 @@ msgid "Invalid file, not an audio bus layout."
msgstr ""
#: editor/editor_audio_buses.cpp
+#, fuzzy
+msgid "Error saving file: %s"
+msgstr "Kļūmes lÄdÄ“jot!"
+
+#: editor/editor_audio_buses.cpp
msgid "Add Bus"
msgstr "Pievienot Kopni"
@@ -2156,10 +2177,6 @@ msgid "New Window"
msgstr ""
#: editor/editor_node.cpp
-msgid "Project export failed with error code %d."
-msgstr ""
-
-#: editor/editor_node.cpp
msgid "Imported resources can't be saved."
msgstr ""
@@ -3007,10 +3024,6 @@ msgstr ""
msgid "Template Package"
msgstr ""
-#: editor/editor_node.cpp editor/project_export.cpp
-msgid "Export Project"
-msgstr ""
-
#: editor/editor_node.cpp
msgid "Export Library"
msgstr ""
@@ -3020,10 +3033,6 @@ msgid "Merge With Existing"
msgstr ""
#: editor/editor_node.cpp
-msgid "Password:"
-msgstr ""
-
-#: editor/editor_node.cpp
msgid "Open & Run a Script"
msgstr ""
@@ -5657,6 +5666,21 @@ 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 ""
@@ -9378,6 +9402,10 @@ msgid "Export PCK/Zip"
msgstr ""
#: editor/project_export.cpp
+msgid "Export Project"
+msgstr ""
+
+#: editor/project_export.cpp
msgid "Export mode?"
msgstr ""
@@ -9468,10 +9496,6 @@ msgid "Couldn't create project.godot in project path."
msgstr ""
#: editor/project_manager.cpp
-msgid "The following files failed extraction from package:"
-msgstr ""
-
-#: editor/project_manager.cpp
msgid "Rename Project"
msgstr ""
@@ -10649,6 +10673,10 @@ msgid "Will load an existing script file."
msgstr "IelÄdÄ“t eksistÄ“joÅ¡u Kopnes IzkÄrtojumu."
#: editor/script_create_dialog.cpp
+msgid "Script file already exists."
+msgstr ""
+
+#: editor/script_create_dialog.cpp
msgid "Class Name:"
msgstr ""
@@ -12214,7 +12242,14 @@ msgid "This node has been deprecated. Use AnimationTree instead."
msgstr ""
#: scene/gui/color_picker.cpp
-msgid "Pick a color from the screen."
+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
diff --git a/editor/translations/mi.po b/editor/translations/mi.po
index af8caa70cc..77c0a220e3 100644
--- a/editor/translations/mi.po
+++ b/editor/translations/mi.po
@@ -1148,10 +1148,22 @@ msgid "Error opening package file, not in ZIP format."
msgstr ""
#: editor/editor_asset_installer.cpp
+msgid "%s (Already Exists)"
+msgstr ""
+
+#: editor/editor_asset_installer.cpp
msgid "Uncompressing Assets"
msgstr ""
#: editor/editor_asset_installer.cpp editor/project_manager.cpp
+msgid "The following files failed extraction from package:"
+msgstr ""
+
+#: editor/editor_asset_installer.cpp
+msgid "And %s more files."
+msgstr ""
+
+#: editor/editor_asset_installer.cpp editor/project_manager.cpp
msgid "Package installed successfully!"
msgstr ""
@@ -1160,6 +1172,10 @@ msgstr ""
msgid "Success!"
msgstr ""
+#: editor/editor_asset_installer.cpp
+msgid "Package Contents:"
+msgstr ""
+
#: editor/editor_asset_installer.cpp editor/editor_node.cpp
msgid "Install"
msgstr ""
@@ -1298,6 +1314,10 @@ msgid "Invalid file, not an audio bus layout."
msgstr ""
#: editor/editor_audio_buses.cpp
+msgid "Error saving file: %s"
+msgstr ""
+
+#: editor/editor_audio_buses.cpp
msgid "Add Bus"
msgstr ""
@@ -2070,10 +2090,6 @@ msgid "New Window"
msgstr ""
#: editor/editor_node.cpp
-msgid "Project export failed with error code %d."
-msgstr ""
-
-#: editor/editor_node.cpp
msgid "Imported resources can't be saved."
msgstr ""
@@ -2912,10 +2928,6 @@ msgstr ""
msgid "Template Package"
msgstr ""
-#: editor/editor_node.cpp editor/project_export.cpp
-msgid "Export Project"
-msgstr ""
-
#: editor/editor_node.cpp
msgid "Export Library"
msgstr ""
@@ -2925,10 +2937,6 @@ msgid "Merge With Existing"
msgstr ""
#: editor/editor_node.cpp
-msgid "Password:"
-msgstr ""
-
-#: editor/editor_node.cpp
msgid "Open & Run a Script"
msgstr ""
@@ -5490,6 +5498,21 @@ 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 ""
@@ -9106,6 +9129,10 @@ msgid "Export PCK/Zip"
msgstr ""
#: editor/project_export.cpp
+msgid "Export Project"
+msgstr ""
+
+#: editor/project_export.cpp
msgid "Export mode?"
msgstr ""
@@ -9196,10 +9223,6 @@ msgid "Couldn't create project.godot in project path."
msgstr ""
#: editor/project_manager.cpp
-msgid "The following files failed extraction from package:"
-msgstr ""
-
-#: editor/project_manager.cpp
msgid "Rename Project"
msgstr ""
@@ -10358,6 +10381,10 @@ msgid "Will load an existing script file."
msgstr ""
#: editor/script_create_dialog.cpp
+msgid "Script file already exists."
+msgstr ""
+
+#: editor/script_create_dialog.cpp
msgid "Class Name:"
msgstr ""
@@ -11883,7 +11910,14 @@ msgid "This node has been deprecated. Use AnimationTree instead."
msgstr ""
#: scene/gui/color_picker.cpp
-msgid "Pick a color from the screen."
+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
diff --git a/editor/translations/ml.po b/editor/translations/ml.po
index e5420f6ac2..765164a24b 100644
--- a/editor/translations/ml.po
+++ b/editor/translations/ml.po
@@ -1158,10 +1158,22 @@ msgid "Error opening package file, not in ZIP format."
msgstr ""
#: editor/editor_asset_installer.cpp
+msgid "%s (Already Exists)"
+msgstr ""
+
+#: editor/editor_asset_installer.cpp
msgid "Uncompressing Assets"
msgstr ""
#: editor/editor_asset_installer.cpp editor/project_manager.cpp
+msgid "The following files failed extraction from package:"
+msgstr ""
+
+#: editor/editor_asset_installer.cpp
+msgid "And %s more files."
+msgstr ""
+
+#: editor/editor_asset_installer.cpp editor/project_manager.cpp
msgid "Package installed successfully!"
msgstr ""
@@ -1170,6 +1182,10 @@ msgstr ""
msgid "Success!"
msgstr ""
+#: editor/editor_asset_installer.cpp
+msgid "Package Contents:"
+msgstr ""
+
#: editor/editor_asset_installer.cpp editor/editor_node.cpp
msgid "Install"
msgstr ""
@@ -1308,6 +1324,10 @@ msgid "Invalid file, not an audio bus layout."
msgstr ""
#: editor/editor_audio_buses.cpp
+msgid "Error saving file: %s"
+msgstr ""
+
+#: editor/editor_audio_buses.cpp
msgid "Add Bus"
msgstr ""
@@ -2081,10 +2101,6 @@ msgid "New Window"
msgstr ""
#: editor/editor_node.cpp
-msgid "Project export failed with error code %d."
-msgstr ""
-
-#: editor/editor_node.cpp
msgid "Imported resources can't be saved."
msgstr ""
@@ -2923,10 +2939,6 @@ msgstr ""
msgid "Template Package"
msgstr ""
-#: editor/editor_node.cpp editor/project_export.cpp
-msgid "Export Project"
-msgstr ""
-
#: editor/editor_node.cpp
msgid "Export Library"
msgstr ""
@@ -2936,10 +2948,6 @@ msgid "Merge With Existing"
msgstr ""
#: editor/editor_node.cpp
-msgid "Password:"
-msgstr ""
-
-#: editor/editor_node.cpp
msgid "Open & Run a Script"
msgstr ""
@@ -5504,6 +5512,21 @@ 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 ""
@@ -9120,6 +9143,10 @@ msgid "Export PCK/Zip"
msgstr ""
#: editor/project_export.cpp
+msgid "Export Project"
+msgstr ""
+
+#: editor/project_export.cpp
msgid "Export mode?"
msgstr ""
@@ -9210,10 +9237,6 @@ msgid "Couldn't create project.godot in project path."
msgstr ""
#: editor/project_manager.cpp
-msgid "The following files failed extraction from package:"
-msgstr ""
-
-#: editor/project_manager.cpp
msgid "Rename Project"
msgstr ""
@@ -10372,6 +10395,10 @@ msgid "Will load an existing script file."
msgstr ""
#: editor/script_create_dialog.cpp
+msgid "Script file already exists."
+msgstr ""
+
+#: editor/script_create_dialog.cpp
msgid "Class Name:"
msgstr ""
@@ -11898,7 +11925,14 @@ msgid "This node has been deprecated. Use AnimationTree instead."
msgstr ""
#: scene/gui/color_picker.cpp
-msgid "Pick a color from the screen."
+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
diff --git a/editor/translations/mr.po b/editor/translations/mr.po
index 84f35123bc..972c843a62 100644
--- a/editor/translations/mr.po
+++ b/editor/translations/mr.po
@@ -2,11 +2,11 @@
# Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur.
# Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md).
# This file is distributed under the same license as the Godot source code.
-# Prachi Joshi <josprachi@yahoo.com>, 2019.
+# Prachi Joshi <josprachi@yahoo.com>, 2019, 2020.
msgid ""
msgstr ""
"Project-Id-Version: Godot Engine editor\n"
-"PO-Revision-Date: 2019-12-22 04:19+0000\n"
+"PO-Revision-Date: 2020-01-11 03:05+0000\n"
"Last-Translator: Prachi Joshi <josprachi@yahoo.com>\n"
"Language-Team: Marathi <https://hosted.weblate.org/projects/godot-engine/"
"godot/mr/>\n"
@@ -14,7 +14,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 3.10\n"
+"X-Generator: Weblate 3.10.1\n"
#: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp
#: modules/visual_script/visual_script_builtin_funcs.cpp
@@ -182,7 +182,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"
@@ -1154,10 +1154,22 @@ msgid "Error opening package file, not in ZIP format."
msgstr ""
#: editor/editor_asset_installer.cpp
+msgid "%s (Already Exists)"
+msgstr ""
+
+#: editor/editor_asset_installer.cpp
msgid "Uncompressing Assets"
msgstr ""
#: editor/editor_asset_installer.cpp editor/project_manager.cpp
+msgid "The following files failed extraction from package:"
+msgstr ""
+
+#: editor/editor_asset_installer.cpp
+msgid "And %s more files."
+msgstr ""
+
+#: editor/editor_asset_installer.cpp editor/project_manager.cpp
msgid "Package installed successfully!"
msgstr ""
@@ -1166,6 +1178,10 @@ msgstr ""
msgid "Success!"
msgstr ""
+#: editor/editor_asset_installer.cpp
+msgid "Package Contents:"
+msgstr ""
+
#: editor/editor_asset_installer.cpp editor/editor_node.cpp
msgid "Install"
msgstr ""
@@ -1304,6 +1320,10 @@ msgid "Invalid file, not an audio bus layout."
msgstr ""
#: editor/editor_audio_buses.cpp
+msgid "Error saving file: %s"
+msgstr ""
+
+#: editor/editor_audio_buses.cpp
msgid "Add Bus"
msgstr ""
@@ -2076,10 +2096,6 @@ msgid "New Window"
msgstr ""
#: editor/editor_node.cpp
-msgid "Project export failed with error code %d."
-msgstr ""
-
-#: editor/editor_node.cpp
msgid "Imported resources can't be saved."
msgstr ""
@@ -2918,10 +2934,6 @@ msgstr ""
msgid "Template Package"
msgstr ""
-#: editor/editor_node.cpp editor/project_export.cpp
-msgid "Export Project"
-msgstr ""
-
#: editor/editor_node.cpp
msgid "Export Library"
msgstr ""
@@ -2931,10 +2943,6 @@ msgid "Merge With Existing"
msgstr ""
#: editor/editor_node.cpp
-msgid "Password:"
-msgstr ""
-
-#: editor/editor_node.cpp
msgid "Open & Run a Script"
msgstr ""
@@ -5496,6 +5504,21 @@ 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 ""
@@ -9112,6 +9135,10 @@ msgid "Export PCK/Zip"
msgstr ""
#: editor/project_export.cpp
+msgid "Export Project"
+msgstr ""
+
+#: editor/project_export.cpp
msgid "Export mode?"
msgstr ""
@@ -9202,10 +9229,6 @@ msgid "Couldn't create project.godot in project path."
msgstr ""
#: editor/project_manager.cpp
-msgid "The following files failed extraction from package:"
-msgstr ""
-
-#: editor/project_manager.cpp
msgid "Rename Project"
msgstr ""
@@ -10364,6 +10387,10 @@ msgid "Will load an existing script file."
msgstr ""
#: editor/script_create_dialog.cpp
+msgid "Script file already exists."
+msgstr ""
+
+#: editor/script_create_dialog.cpp
msgid "Class Name:"
msgstr ""
@@ -11889,7 +11916,14 @@ msgid "This node has been deprecated. Use AnimationTree instead."
msgstr ""
#: scene/gui/color_picker.cpp
-msgid "Pick a color from the screen."
+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
diff --git a/editor/translations/ms.po b/editor/translations/ms.po
index dc75443acb..8e5602be96 100644
--- a/editor/translations/ms.po
+++ b/editor/translations/ms.po
@@ -1176,10 +1176,22 @@ msgid "Error opening package file, not in ZIP format."
msgstr ""
#: editor/editor_asset_installer.cpp
+msgid "%s (Already Exists)"
+msgstr ""
+
+#: editor/editor_asset_installer.cpp
msgid "Uncompressing Assets"
msgstr ""
#: editor/editor_asset_installer.cpp editor/project_manager.cpp
+msgid "The following files failed extraction from package:"
+msgstr ""
+
+#: editor/editor_asset_installer.cpp
+msgid "And %s more files."
+msgstr ""
+
+#: editor/editor_asset_installer.cpp editor/project_manager.cpp
msgid "Package installed successfully!"
msgstr ""
@@ -1188,6 +1200,10 @@ msgstr ""
msgid "Success!"
msgstr ""
+#: editor/editor_asset_installer.cpp
+msgid "Package Contents:"
+msgstr ""
+
#: editor/editor_asset_installer.cpp editor/editor_node.cpp
msgid "Install"
msgstr ""
@@ -1326,6 +1342,10 @@ msgid "Invalid file, not an audio bus layout."
msgstr ""
#: editor/editor_audio_buses.cpp
+msgid "Error saving file: %s"
+msgstr ""
+
+#: editor/editor_audio_buses.cpp
msgid "Add Bus"
msgstr ""
@@ -2100,10 +2120,6 @@ msgid "New Window"
msgstr ""
#: editor/editor_node.cpp
-msgid "Project export failed with error code %d."
-msgstr ""
-
-#: editor/editor_node.cpp
msgid "Imported resources can't be saved."
msgstr ""
@@ -2944,10 +2960,6 @@ msgstr ""
msgid "Template Package"
msgstr ""
-#: editor/editor_node.cpp editor/project_export.cpp
-msgid "Export Project"
-msgstr ""
-
#: editor/editor_node.cpp
msgid "Export Library"
msgstr ""
@@ -2957,10 +2969,6 @@ msgid "Merge With Existing"
msgstr ""
#: editor/editor_node.cpp
-msgid "Password:"
-msgstr ""
-
-#: editor/editor_node.cpp
msgid "Open & Run a Script"
msgstr ""
@@ -5541,6 +5549,21 @@ 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 ""
@@ -9178,6 +9201,10 @@ msgid "Export PCK/Zip"
msgstr ""
#: editor/project_export.cpp
+msgid "Export Project"
+msgstr ""
+
+#: editor/project_export.cpp
msgid "Export mode?"
msgstr ""
@@ -9268,10 +9295,6 @@ msgid "Couldn't create project.godot in project path."
msgstr ""
#: editor/project_manager.cpp
-msgid "The following files failed extraction from package:"
-msgstr ""
-
-#: editor/project_manager.cpp
msgid "Rename Project"
msgstr ""
@@ -10435,6 +10458,10 @@ msgid "Will load an existing script file."
msgstr ""
#: editor/script_create_dialog.cpp
+msgid "Script file already exists."
+msgstr ""
+
+#: editor/script_create_dialog.cpp
msgid "Class Name:"
msgstr ""
@@ -11970,7 +11997,14 @@ msgid "This node has been deprecated. Use AnimationTree instead."
msgstr ""
#: scene/gui/color_picker.cpp
-msgid "Pick a color from the screen."
+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
diff --git a/editor/translations/nb.po b/editor/translations/nb.po
index e05c2e5ec8..d4f7d1ec99 100644
--- a/editor/translations/nb.po
+++ b/editor/translations/nb.po
@@ -1258,10 +1258,24 @@ msgid "Error opening package file, not in ZIP format."
msgstr "Feil ved åpning av pakkefil, ikke i zip format."
#: editor/editor_asset_installer.cpp
+#, fuzzy
+msgid "%s (Already Exists)"
+msgstr "Eksisterer allerede"
+
+#: editor/editor_asset_installer.cpp
msgid "Uncompressing Assets"
msgstr "Dekomprimerer Ressurser"
#: editor/editor_asset_installer.cpp editor/project_manager.cpp
+msgid "The following files failed extraction from package:"
+msgstr "De følgende filene feilet ekstrahering fra pakke:"
+
+#: editor/editor_asset_installer.cpp
+#, fuzzy
+msgid "And %s more files."
+msgstr "%d flere filer"
+
+#: editor/editor_asset_installer.cpp editor/project_manager.cpp
#, fuzzy
msgid "Package installed successfully!"
msgstr "Vellykket Installering av Pakke!"
@@ -1271,6 +1285,11 @@ msgstr "Vellykket Installering av Pakke!"
msgid "Success!"
msgstr "Suksess!"
+#: editor/editor_asset_installer.cpp
+#, fuzzy
+msgid "Package Contents:"
+msgstr "Innhold:"
+
#: editor/editor_asset_installer.cpp editor/editor_node.cpp
msgid "Install"
msgstr "Installer"
@@ -1411,6 +1430,11 @@ 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!"
+
+#: editor/editor_audio_buses.cpp
msgid "Add Bus"
msgstr "Legg til Bus"
@@ -2268,10 +2292,6 @@ msgid "New Window"
msgstr "Nytt vindu"
#: editor/editor_node.cpp
-msgid "Project export failed with error code %d."
-msgstr "Eksport av prosjektet mislyktes med feilkode %d."
-
-#: editor/editor_node.cpp
msgid "Imported resources can't be saved."
msgstr "Importerte ressurser kan ikke lagres."
@@ -3215,10 +3235,6 @@ msgstr "Importer Mal Fra ZIP-Fil"
msgid "Template Package"
msgstr "Eksporter Mal-Manager"
-#: editor/editor_node.cpp editor/project_export.cpp
-msgid "Export Project"
-msgstr "Eksporter Prosjekt"
-
#: editor/editor_node.cpp
msgid "Export Library"
msgstr "Eksporter Bibliotek"
@@ -3228,10 +3244,6 @@ msgid "Merge With Existing"
msgstr "Slå sammen Med Eksisterende"
#: editor/editor_node.cpp
-msgid "Password:"
-msgstr "Passord:"
-
-#: editor/editor_node.cpp
msgid "Open & Run a Script"
msgstr "Åpne & Kjør et Skript"
@@ -6065,6 +6077,22 @@ 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
+#, fuzzy
+msgid "Directed Border Pixels"
+msgstr "Mapper og Filer:"
+
+#: editor/plugins/cpu_particles_2d_editor_plugin.cpp
+#: editor/plugins/particles_2d_editor_plugin.cpp
msgid "Capture from Pixel"
msgstr ""
@@ -9930,6 +9958,10 @@ msgid "Export PCK/Zip"
msgstr ""
#: editor/project_export.cpp
+msgid "Export Project"
+msgstr "Eksporter Prosjekt"
+
+#: editor/project_export.cpp
#, fuzzy
msgid "Export mode?"
msgstr "Eksporter Prosjekt"
@@ -10028,10 +10060,6 @@ msgid "Couldn't create project.godot in project path."
msgstr "Kunne ikke lage project.godot i prosjektstien."
#: editor/project_manager.cpp
-msgid "The following files failed extraction from package:"
-msgstr "De følgende filene feilet ekstrahering fra pakke:"
-
-#: editor/project_manager.cpp
msgid "Rename Project"
msgstr "Endre Navn på Prosjekt"
@@ -11271,6 +11299,11 @@ msgstr "Last et eksisterende Bus oppsett."
#: editor/script_create_dialog.cpp
#, fuzzy
+msgid "Script file already exists."
+msgstr "Eksisterer allerede"
+
+#: editor/script_create_dialog.cpp
+#, fuzzy
msgid "Class Name:"
msgstr "Klasse:"
@@ -12885,7 +12918,14 @@ msgid "This node has been deprecated. Use AnimationTree instead."
msgstr ""
#: scene/gui/color_picker.cpp
-msgid "Pick a color from the screen."
+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
@@ -12991,6 +13031,12 @@ msgstr ""
msgid "Constants cannot be modified."
msgstr "Konstanter kan ikke endres."
+#~ msgid "Project export failed with error code %d."
+#~ msgstr "Eksport av prosjektet mislyktes med feilkode %d."
+
+#~ msgid "Password:"
+#~ msgstr "Passord:"
+
#~ msgid "Pause the scene"
#~ msgstr "Pause scenen"
@@ -13182,9 +13228,6 @@ msgstr "Konstanter kan ikke endres."
#~ msgid "Create folder"
#~ msgstr "Opprett mappe"
-#~ msgid "Already existing"
-#~ msgstr "Eksisterer allerede"
-
#, fuzzy
#~ msgid "Custom Node"
#~ msgstr "Kutt Noder"
@@ -13222,10 +13265,6 @@ msgstr "Konstanter kan ikke endres."
#~ msgstr "Kol:"
#, fuzzy
-#~ msgid "Split already exists."
-#~ msgstr "Eksisterer allerede"
-
-#, fuzzy
#~ msgid "Add Split"
#~ msgstr "Legg til punkt"
diff --git a/editor/translations/nl.po b/editor/translations/nl.po
index 1e3bd204af..87f02bce48 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.
+# Stijn Hinlopen <f.a.hinlopen@gmail.com>, 2019, 2020.
# jef dered <themen098s@vivaldi.net>, 2019.
# Alex H. <sandertjeh13@hotmail.com>, 2019.
# edouardgr <edouard.gruyters@gmail.com>, 2019.
@@ -44,7 +44,7 @@ msgid ""
msgstr ""
"Project-Id-Version: Godot Engine editor\n"
"POT-Creation-Date: \n"
-"PO-Revision-Date: 2019-12-27 15:52+0000\n"
+"PO-Revision-Date: 2020-01-12 13:26+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"
@@ -53,7 +53,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 3.10\n"
+"X-Generator: Weblate 3.10.1\n"
#: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp
#: modules/visual_script/visual_script_builtin_funcs.cpp
@@ -158,7 +158,7 @@ msgstr "Geselecteerde sleutel(s) dupliceren"
#: editor/animation_bezier_editor.cpp
msgid "Delete Selected Key(s)"
-msgstr "Geselecteerde Key(s) Verwijderen"
+msgstr "Geselecteerde sleutel(s) verwijderen"
#: editor/animation_bezier_editor.cpp
msgid "Add Bezier Point"
@@ -174,11 +174,11 @@ msgstr "Animatiesleutels dupliceren"
#: editor/animation_bezier_editor.cpp editor/animation_track_editor.cpp
msgid "Anim Delete Keys"
-msgstr "Anim Verwijder Keys"
+msgstr "Animsleutels verwijderen"
#: editor/animation_track_editor.cpp
msgid "Anim Change Keyframe Time"
-msgstr "Anim Wijzig Keyframe Waarde"
+msgstr "Anim Keyframe-tijd wijzigen"
#: editor/animation_track_editor.cpp
msgid "Anim Change Transition"
@@ -190,7 +190,7 @@ msgstr "Anim Wijzig Transform"
#: editor/animation_track_editor.cpp
msgid "Anim Change Keyframe Value"
-msgstr "Anim Wijzig Keyframe Waarde"
+msgstr "Anim Keyframe-waarde wijzigen"
#: editor/animation_track_editor.cpp
msgid "Anim Change Call"
@@ -198,7 +198,7 @@ msgstr "Anim Wijzig Aanroep"
#: editor/animation_track_editor.cpp
msgid "Anim Multi Change Keyframe Time"
-msgstr "Anim Wijzig Meerdere Keyframe Waarden"
+msgstr "Anim Multi Keyframe-tijd wijzigen"
#: editor/animation_track_editor.cpp
msgid "Anim Multi Change Transition"
@@ -351,7 +351,7 @@ msgstr "Naadloze lusinterpolatie"
#: editor/animation_track_editor.cpp
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Insert Key"
-msgstr "Voer Sleutel in"
+msgstr "Sleutel invoeren"
#: editor/animation_track_editor.cpp
msgid "Duplicate Key(s)"
@@ -359,7 +359,7 @@ msgstr "Sleutel(s) dupliceren"
#: editor/animation_track_editor.cpp
msgid "Delete Key(s)"
-msgstr "Verwijder Sleutel(s)"
+msgstr "Sleutel(s) verwijderen"
#: editor/animation_track_editor.cpp
msgid "Change Animation Update Mode"
@@ -379,11 +379,11 @@ msgstr "Verwijder Anim Track"
#: editor/animation_track_editor.cpp
msgid "Create NEW track for %s and insert key?"
-msgstr "NIEUWE track aanmaken voor %s en key invoegen?"
+msgstr "NIEUW spoor aanmaken voor %s en sleutel invoegen?"
#: editor/animation_track_editor.cpp
msgid "Create %d NEW tracks and insert keys?"
-msgstr "Maak %d NIEUWE tracks aan en keys invoeren?"
+msgstr "Maak %d NIEUWE sporen aan en voer sleutels in?"
#: editor/animation_track_editor.cpp editor/create_dialog.cpp
#: editor/editor_audio_buses.cpp editor/editor_feature_profile.cpp
@@ -455,7 +455,7 @@ msgstr "Niet mogelijk om een nieuwe track toe te voegen zonder een root"
#: editor/animation_track_editor.cpp
msgid "Invalid track for Bezier (no suitable sub-properties)"
-msgstr ""
+msgstr "Ongeldig spoor voor Bezier (geen geschikte sub-eigenschappen)"
#: editor/animation_track_editor.cpp
msgid "Add Bezier Track"
@@ -463,11 +463,11 @@ msgstr "Voeg Bézierbaan Toe"
#: editor/animation_track_editor.cpp
msgid "Track path is invalid, so can't add a key."
-msgstr "Track path is niet geldig, dus kan geen key toevoegen."
+msgstr "Spoorpad is ongeldig, dus sleutel kan niet toevoegt worden."
#: editor/animation_track_editor.cpp
msgid "Track is not of type Spatial, can't insert key"
-msgstr "Track is niet van het type Spatial, kan geen key invoegen"
+msgstr "Spoor is niet van het type Spatial, kan geen sleutel invoegen"
#: editor/animation_track_editor.cpp
msgid "Add Transform Track Key"
@@ -1230,10 +1230,24 @@ msgid "Error opening package file, not in ZIP format."
msgstr "Fout bij het openen van het pakketbestand, geen zip-formaat."
#: editor/editor_asset_installer.cpp
+#, fuzzy
+msgid "%s (Already Exists)"
+msgstr "Bestaat al"
+
+#: editor/editor_asset_installer.cpp
msgid "Uncompressing Assets"
msgstr "Bronnen aan het uitpakken"
#: editor/editor_asset_installer.cpp editor/project_manager.cpp
+msgid "The following files failed extraction from package:"
+msgstr "De volgende bestanden konden niet worden uitgepakt:"
+
+#: editor/editor_asset_installer.cpp
+#, fuzzy
+msgid "And %s more files."
+msgstr "nog %d bestand(en)"
+
+#: editor/editor_asset_installer.cpp editor/project_manager.cpp
msgid "Package installed successfully!"
msgstr "Pakket succesvol geïnstalleerd!"
@@ -1242,6 +1256,11 @@ msgstr "Pakket succesvol geïnstalleerd!"
msgid "Success!"
msgstr "Gelukt!"
+#: editor/editor_asset_installer.cpp
+#, fuzzy
+msgid "Package Contents:"
+msgstr "Inhoud:"
+
#: editor/editor_asset_installer.cpp editor/editor_node.cpp
msgid "Install"
msgstr "Installeer"
@@ -1380,6 +1399,11 @@ msgid "Invalid file, not an audio bus layout."
msgstr "Ongeldig bestand, geen audiobus layout."
#: editor/editor_audio_buses.cpp
+#, fuzzy
+msgid "Error saving file: %s"
+msgstr "Error bij het opslaan van bestand!"
+
+#: editor/editor_audio_buses.cpp
msgid "Add Bus"
msgstr "Bus Toevoegen"
@@ -1439,7 +1463,7 @@ msgstr "Mag niet conflicteren met de naam van een bestaande globale constante."
#: editor/editor_autoload_settings.cpp
msgid "Keyword cannot be used as an autoload name."
-msgstr "Sleutelwoorden mogen niet gebruikt worden als autoload naam."
+msgstr "Gereserveerd woord mag niet gebruikt worden als autoloadnaam."
#: editor/editor_autoload_settings.cpp
msgid "Autoload '%s' already exists!"
@@ -2031,9 +2055,8 @@ msgid "Case Sensitive"
msgstr "Hoofdlettergevoelig"
#: editor/editor_help_search.cpp
-#, fuzzy
msgid "Show Hierarchy"
-msgstr "Toon helpers"
+msgstr "Toon hiërarchie"
#: editor/editor_help_search.cpp
msgid "Display All"
@@ -2072,9 +2095,8 @@ msgid "Class"
msgstr "Klasse"
#: editor/editor_help_search.cpp
-#, fuzzy
msgid "Method"
-msgstr "Methodes"
+msgstr "Methode"
#: editor/editor_help_search.cpp editor/plugins/script_text_editor.cpp
msgid "Signal"
@@ -2085,14 +2107,12 @@ msgid "Constant"
msgstr "Constante"
#: editor/editor_help_search.cpp
-#, fuzzy
msgid "Property"
-msgstr "Eigenschap:"
+msgstr "Eigenschap"
#: editor/editor_help_search.cpp
-#, fuzzy
msgid "Theme Property"
-msgstr "Thema Eigenschappen"
+msgstr "Thema-eigenschap"
#: editor/editor_inspector.cpp editor/project_settings_editor.cpp
msgid "Property:"
@@ -2175,10 +2195,6 @@ msgid "New Window"
msgstr "Nieuw Venster"
#: editor/editor_node.cpp
-msgid "Project export failed with error code %d."
-msgstr "Project exporteren faalt door foutcode %d."
-
-#: editor/editor_node.cpp
msgid "Imported resources can't be saved."
msgstr "Geïmporteerde bronnen kunnen niet opgeslagen worden."
@@ -2766,11 +2782,11 @@ msgstr "Versiebeheer"
#: editor/editor_node.cpp editor/plugins/version_control_editor_plugin.cpp
msgid "Set Up Version Control"
-msgstr "Versiebeheer Instellen"
+msgstr "Versiebeheer instellen"
#: editor/editor_node.cpp
msgid "Shut Down Version Control"
-msgstr "Versiebeheer Afsluiten"
+msgstr "Versiebeheer afsluiten"
#: editor/editor_node.cpp
msgid "Export..."
@@ -3100,10 +3116,6 @@ msgstr "Sjablonen importeren Vanuit ZIP-Bestand"
msgid "Template Package"
msgstr "Export Sjabloon Manager"
-#: editor/editor_node.cpp editor/project_export.cpp
-msgid "Export Project"
-msgstr "Project Exporteren"
-
#: editor/editor_node.cpp
msgid "Export Library"
msgstr "Bibliotheek Exporteren"
@@ -3113,10 +3125,6 @@ msgid "Merge With Existing"
msgstr "Met bestaande samenvoegen"
#: editor/editor_node.cpp
-msgid "Password:"
-msgstr "Wachtwoord:"
-
-#: editor/editor_node.cpp
msgid "Open & Run a Script"
msgstr "Voer Een Script Uit"
@@ -3359,7 +3367,7 @@ msgstr "Verwijder Item"
#: editor/editor_properties_array_dict.cpp
msgid "New Key:"
-msgstr "Nieuwe Sleutel:"
+msgstr "Nieuwe sleutel:"
#: editor/editor_properties_array_dict.cpp
msgid "New Value:"
@@ -3367,7 +3375,7 @@ msgstr "Nieuwe Waarde:"
#: editor/editor_properties_array_dict.cpp
msgid "Add Key/Value Pair"
-msgstr "Sleutel-Waarde Paar Toevoegen"
+msgstr "Sleutel/waarde-paar toevoegen"
#: editor/editor_run_native.cpp
msgid ""
@@ -3480,13 +3488,14 @@ msgid "Importing:"
msgstr "Bezit met importeren:"
#: editor/export_template_manager.cpp
-#, fuzzy
msgid "Error getting the list of mirrors."
-msgstr "Error bij het maken van het signatuur object."
+msgstr "Fout bij het laden van spiegelservers."
#: editor/export_template_manager.cpp
msgid "Error parsing JSON of mirror list. Please report this issue!"
msgstr ""
+"Fout bij het inlezen van spiegelserverlijst (JSON). Meld deze fout "
+"alstublieft!"
#: editor/export_template_manager.cpp
msgid ""
@@ -4671,9 +4680,8 @@ msgid "Move Node"
msgstr "Knoop verplaatsen"
#: editor/plugins/animation_state_machine_editor.cpp
-#, fuzzy
msgid "Transition exists!"
-msgstr "Overgang: "
+msgstr "Overgang bestaat!"
#: editor/plugins/animation_state_machine_editor.cpp
msgid "Add Transition"
@@ -4975,7 +4983,7 @@ msgstr "Gekregen:"
#: editor/plugins/asset_library_editor_plugin.cpp
msgid "Failed sha256 hash check"
-msgstr "Sha256 hash controle mislukt"
+msgstr "SHA256-proef mislukt"
#: editor/plugins/asset_library_editor_plugin.cpp
msgid "Asset Download Error:"
@@ -5613,15 +5621,15 @@ msgstr "Voorbeeld Canvas Schaal"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Translation mask for inserting keys."
-msgstr "Vertaalomslag voor het invoegen van sleutels."
+msgstr "Translatiemasker voor sleutelinvoer."
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Rotation mask for inserting keys."
-msgstr "Rotatiemasker voor het invoegen van sleutels."
+msgstr "Rotatiemasker voor sleutelinvoer."
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Scale mask for inserting keys."
-msgstr "Schaalmasker voor het invoegen van sleutels."
+msgstr "Schaalmasker voor sleutelinvoer."
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Insert keys (based on mask)."
@@ -5634,19 +5642,19 @@ msgid ""
"Keys are only added to existing tracks, no new tracks will be created.\n"
"Keys must be inserted manually for the first time."
msgstr ""
-"Automatisch sleutels invoegen als objecten verschuiven, geroteerd of "
+"Automatisch sleutels invoegen als objecten verschuift, geroteerd of "
"geschaald worden (op basis van masker).\n"
-"Sleutels worden alleen toegevoegd aan bestaande tracks, er worden geen "
-"nieuwe tracks aangemaakt.\n"
+"Sleutels worden alleen toegevoegd aan bestaande sporen, er worden geen "
+"nieuwe sporen aangemaakt.\n"
"De eerste keer moeten sleutels handmatig ingevoerd worden."
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Auto Insert Key"
-msgstr "Automatisch Sleutel invoegen"
+msgstr "Sleutel automatisch invoegen"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Insert Key (Existing Tracks)"
-msgstr "Sleutel invoegen (in bestaande banen)"
+msgstr "Sleutel invoegen (in bestaande sporen)"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Copy Pose"
@@ -5753,6 +5761,23 @@ msgstr "Emissiemasker"
#: editor/plugins/cpu_particles_2d_editor_plugin.cpp
#: editor/plugins/particles_2d_editor_plugin.cpp
+#, fuzzy
+msgid "Solid Pixels"
+msgstr "Krimpen (Pixels): "
+
+#: 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
+#, fuzzy
+msgid "Directed Border Pixels"
+msgstr "Mappen & Bestanden:"
+
+#: editor/plugins/cpu_particles_2d_editor_plugin.cpp
+#: editor/plugins/particles_2d_editor_plugin.cpp
msgid "Capture from Pixel"
msgstr "Neem uit Pixel"
@@ -5978,18 +6003,19 @@ msgstr "Omlijningsgrootte:"
#: editor/plugins/mesh_instance_editor_plugin.cpp
msgid "UV Channel Debug"
-msgstr ""
+msgstr "UV-kanaal debug"
#: editor/plugins/mesh_library_editor_plugin.cpp
msgid "Remove item %d?"
msgstr "Element %d verwijderen?"
#: editor/plugins/mesh_library_editor_plugin.cpp
-#, fuzzy
msgid ""
"Update from existing scene?:\n"
"%s"
-msgstr "Update Vanuit Scene"
+msgstr ""
+"Update vanuit bestaande scène?:\n"
+"%s"
#: editor/plugins/mesh_library_editor_plugin.cpp
msgid "Mesh Library"
@@ -6232,7 +6258,7 @@ msgstr "Selecteer Punten"
#: editor/plugins/path_2d_editor_plugin.cpp
#: editor/plugins/path_editor_plugin.cpp
msgid "Shift+Drag: Select Control Points"
-msgstr "Shift+Drag: Selecteer Controle Punten"
+msgstr "Shift+Slepen: selecteer controlepunten"
#: editor/plugins/path_2d_editor_plugin.cpp
#: editor/plugins/path_editor_plugin.cpp
@@ -6250,7 +6276,7 @@ msgstr "Rechter Klik: Verwijder Punt"
#: editor/plugins/path_2d_editor_plugin.cpp
msgid "Select Control Points (Shift+Drag)"
-msgstr "Selecteer Controle Punten (Shift+Sleep)"
+msgstr "Selecteer controlepunten (Shift+Slepen)"
#: editor/plugins/path_2d_editor_plugin.cpp
#: editor/plugins/path_editor_plugin.cpp
@@ -7149,11 +7175,11 @@ msgstr "Roteren %s graden."
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Keying is disabled (no key inserted)."
-msgstr "Key-en is uitgeschakeld (geen key ingevoegd)."
+msgstr "Sleutelinvoer is uitgeschakeld (geen sleutel ingevoegd)."
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Animation Key Inserted."
-msgstr "Animatie Key Ingevoegd."
+msgstr "Animatiesleutel Ingevoegd."
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Pitch"
@@ -7404,7 +7430,7 @@ msgstr "Schakel Perspectief/Orthogonaal Zicht"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Insert Animation Key"
-msgstr "Voeg Animatiesleutel toe"
+msgstr "Animatiesleutel invoegen"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Focus Origin"
@@ -7541,9 +7567,8 @@ msgid "Create Mesh2D"
msgstr "Creëer Mesh2D"
#: editor/plugins/sprite_editor_plugin.cpp
-#, fuzzy
msgid "Mesh2D Preview"
-msgstr "Creëren van Mesh Previews"
+msgstr "Mesh2D Voorbeeldweergave"
#: editor/plugins/sprite_editor_plugin.cpp
msgid "Create Polygon2D"
@@ -7551,25 +7576,23 @@ msgstr "Creëer Polygon2D"
#: editor/plugins/sprite_editor_plugin.cpp
msgid "Polygon2D Preview"
-msgstr ""
+msgstr "Polygon2D Voorbeeldweergave"
#: editor/plugins/sprite_editor_plugin.cpp
msgid "Create CollisionPolygon2D"
msgstr "Creëer CollisionPolygon2D"
#: editor/plugins/sprite_editor_plugin.cpp
-#, fuzzy
msgid "CollisionPolygon2D Preview"
-msgstr "Creëer CollisionPolygon2D"
+msgstr "CollisionPolygon2D Voorbeeldweergave"
#: editor/plugins/sprite_editor_plugin.cpp
msgid "Create LightOccluder2D"
msgstr "Creëer LightOccluder2D"
#: editor/plugins/sprite_editor_plugin.cpp
-#, fuzzy
msgid "LightOccluder2D Preview"
-msgstr "Creëer LightOccluder2D"
+msgstr "LightOccluder2D Voorbeeldweergave"
#: editor/plugins/sprite_editor_plugin.cpp
msgid "Sprite is empty!"
@@ -7650,9 +7673,8 @@ msgid "Add Frame"
msgstr "Voeg Frame toe"
#: editor/plugins/sprite_frames_editor_plugin.cpp
-#, fuzzy
msgid "Unable to load images"
-msgstr "Bron laden mislukt."
+msgstr "Afbeeldingen laden mislukt"
#: editor/plugins/sprite_frames_editor_plugin.cpp
msgid "ERROR: Couldn't load frame resource!"
@@ -8341,14 +8363,12 @@ msgid "Edit Tile Z Index"
msgstr "Bewerk Tile Z Index"
#: editor/plugins/tile_set_editor_plugin.cpp
-#, fuzzy
msgid "Make Convex"
-msgstr "Creëer Polygon Convex"
+msgstr "Maak convex"
#: editor/plugins/tile_set_editor_plugin.cpp
-#, fuzzy
msgid "Make Concave"
-msgstr "Creëer Polygon Concave"
+msgstr "Maak concaaf"
#: editor/plugins/tile_set_editor_plugin.cpp
msgid "Create Collision Polygon"
@@ -8392,7 +8412,7 @@ msgstr "VCS Addon is niet geïnitialiseerd"
#: editor/plugins/version_control_editor_plugin.cpp
msgid "Version Control System"
-msgstr "Versie Controle Systeem"
+msgstr "Versiebeheersysteem"
#: editor/plugins/version_control_editor_plugin.cpp
msgid "Initialize"
@@ -9502,21 +9522,25 @@ msgstr "Gecompileerd"
#: editor/project_export.cpp
msgid "Encrypted (Provide Key Below)"
-msgstr "Versleuteld (Verstrek hieronder de sleutel)"
+msgstr "Versleuteld (verstrek hieronder de sleutel)"
#: editor/project_export.cpp
msgid "Invalid Encryption Key (must be 64 characters long)"
-msgstr "Ongeldige Encryptiesleutel (moet 64 tekens lang zijn)"
+msgstr "Ongeldige encryptiesleutel (moet 64 tekens lang zijn)"
#: editor/project_export.cpp
msgid "Script Encryption Key (256-bits as hex):"
-msgstr "Script Encryptiesleutel (256-bits als hexadecimale):"
+msgstr "Script encryptiesleutel (256-bits als hexadecimaal):"
#: editor/project_export.cpp
msgid "Export PCK/Zip"
msgstr "Exporteer PCK/Zip"
#: editor/project_export.cpp
+msgid "Export Project"
+msgstr "Project Exporteren"
+
+#: editor/project_export.cpp
msgid "Export mode?"
msgstr "Exporteer modus?"
@@ -9609,10 +9633,6 @@ msgid "Couldn't create project.godot in project path."
msgstr "Kan project.godot niet in projectpad maken."
#: editor/project_manager.cpp
-msgid "The following files failed extraction from package:"
-msgstr "De volgende bestanden konden niet worden uitgepakt:"
-
-#: editor/project_manager.cpp
msgid "Rename Project"
msgstr "Project hernoemen"
@@ -9877,15 +9897,15 @@ msgstr ""
#: editor/project_settings_editor.cpp
msgid "Key "
-msgstr "Sleutel "
+msgstr "Toets "
#: editor/project_settings_editor.cpp
msgid "Joy Button"
-msgstr "Controller Knop"
+msgstr "Controllerknop"
#: editor/project_settings_editor.cpp
msgid "Joy Axis"
-msgstr "Controller Axis"
+msgstr "Controller-as"
#: editor/project_settings_editor.cpp
msgid "Mouse Button"
@@ -9969,7 +9989,7 @@ msgstr "X Knop 2"
#: editor/project_settings_editor.cpp
msgid "Joypad Axis Index:"
-msgstr "Controller Axis Index:"
+msgstr "Controller-as index:"
#: editor/project_settings_editor.cpp
msgid "Axis"
@@ -9977,7 +9997,7 @@ msgstr "As"
#: editor/project_settings_editor.cpp
msgid "Joypad Button Index:"
-msgstr "Controller Knop Index:"
+msgstr "Controllerknop index:"
#: editor/project_settings_editor.cpp
msgid "Erase Input Action"
@@ -10526,15 +10546,15 @@ msgstr "Nieuwe wortel Scene"
#: editor/scene_tree_dock.cpp
msgid "Create Root Node:"
-msgstr "Wortelknoop maken:"
+msgstr "Maak de wortelknoop:"
#: editor/scene_tree_dock.cpp
msgid "2D Scene"
-msgstr "2D Scene"
+msgstr "2D Scène"
#: editor/scene_tree_dock.cpp
msgid "3D Scene"
-msgstr "3D Scene"
+msgstr "3D Scène"
#: editor/scene_tree_dock.cpp
msgid "User Interface"
@@ -10853,6 +10873,11 @@ msgid "Will load an existing script file."
msgstr "Laad bestaand script."
#: editor/script_create_dialog.cpp
+#, fuzzy
+msgid "Script file already exists."
+msgstr "Bestaat al"
+
+#: editor/script_create_dialog.cpp
msgid "Class Name:"
msgstr "Klasse Naam:"
@@ -10994,7 +11019,7 @@ msgstr "Overig"
#: editor/script_editor_debugger.cpp
msgid "Clicked Control:"
-msgstr "Control aangeklikt:"
+msgstr "Control-knoop aangeklikt:"
#: editor/script_editor_debugger.cpp
msgid "Clicked Control Type:"
@@ -11302,9 +11327,8 @@ msgid "Cursor Clear Rotation"
msgstr "Cursorrotatie wissen"
#: modules/gridmap/grid_map_editor_plugin.cpp
-#, fuzzy
msgid "Paste Selects"
-msgstr "Selectie Verwijderen"
+msgstr "Plakken Selecteren"
#: modules/gridmap/grid_map_editor_plugin.cpp
msgid "Clear Selection"
@@ -12241,7 +12265,7 @@ msgid ""
"The controller ID must not be 0 or this controller won't be bound to an "
"actual controller."
msgstr ""
-"Het controller ID moet ongelijk 0 zijn, anders zal deze controller niet "
+"Het controller ID moet ongelijk aan 0 zijn, anders zal deze controller niet "
"verbonden worden met een werkelijke controller."
#: scene/3d/arvr_nodes.cpp
@@ -12527,7 +12551,15 @@ msgid "This node has been deprecated. Use AnimationTree instead."
msgstr "Deze knoop is verouderd. Gebruik in plaats daarvan AnimationTree."
#: scene/gui/color_picker.cpp
-msgid "Pick a color from the screen."
+msgid ""
+"Color: #%s\n"
+"LMB: Set color\n"
+"RMB: Remove preset"
+msgstr ""
+
+#: scene/gui/color_picker.cpp
+#, fuzzy
+msgid "Pick a color from the editor window."
msgstr "Kies een kleur van het scherm."
#: scene/gui/color_picker.cpp
@@ -12650,6 +12682,12 @@ msgstr "Varyings kunnen alleen worden toegewezenin vertex functies."
msgid "Constants cannot be modified."
msgstr "Constanten kunnen niet worden aangepast."
+#~ msgid "Project export failed with error code %d."
+#~ msgstr "Project exporteren faalt door foutcode %d."
+
+#~ msgid "Password:"
+#~ msgstr "Wachtwoord:"
+
#~ msgid "Pause the scene"
#~ msgstr "Pauzeer de scene"
@@ -12911,9 +12949,6 @@ msgstr "Constanten kunnen niet worden aangepast."
#~ msgid "Create folder"
#~ msgstr "Map Maken"
-#~ msgid "Already existing"
-#~ msgstr "Bestaat al"
-
#, fuzzy
#~ msgid "Custom Node"
#~ msgstr "Knip Nodes"
@@ -12963,10 +12998,6 @@ msgstr "Constanten kunnen niet worden aangepast."
#~ "PathFollow2D werkt alleen wanneer het een kind van een Path2D node is."
#, fuzzy
-#~ msgid "Split already exists."
-#~ msgstr "Bestaat al"
-
-#, fuzzy
#~ msgid "Add Split"
#~ msgstr "Punt toevoegen"
diff --git a/editor/translations/or.po b/editor/translations/or.po
index 2cde4699f1..881d3aee64 100644
--- a/editor/translations/or.po
+++ b/editor/translations/or.po
@@ -1154,10 +1154,22 @@ msgid "Error opening package file, not in ZIP format."
msgstr ""
#: editor/editor_asset_installer.cpp
+msgid "%s (Already Exists)"
+msgstr ""
+
+#: editor/editor_asset_installer.cpp
msgid "Uncompressing Assets"
msgstr ""
#: editor/editor_asset_installer.cpp editor/project_manager.cpp
+msgid "The following files failed extraction from package:"
+msgstr ""
+
+#: editor/editor_asset_installer.cpp
+msgid "And %s more files."
+msgstr ""
+
+#: editor/editor_asset_installer.cpp editor/project_manager.cpp
msgid "Package installed successfully!"
msgstr ""
@@ -1166,6 +1178,10 @@ msgstr ""
msgid "Success!"
msgstr ""
+#: editor/editor_asset_installer.cpp
+msgid "Package Contents:"
+msgstr ""
+
#: editor/editor_asset_installer.cpp editor/editor_node.cpp
msgid "Install"
msgstr ""
@@ -1304,6 +1320,10 @@ msgid "Invalid file, not an audio bus layout."
msgstr ""
#: editor/editor_audio_buses.cpp
+msgid "Error saving file: %s"
+msgstr ""
+
+#: editor/editor_audio_buses.cpp
msgid "Add Bus"
msgstr ""
@@ -2076,10 +2096,6 @@ msgid "New Window"
msgstr ""
#: editor/editor_node.cpp
-msgid "Project export failed with error code %d."
-msgstr ""
-
-#: editor/editor_node.cpp
msgid "Imported resources can't be saved."
msgstr ""
@@ -2918,10 +2934,6 @@ msgstr ""
msgid "Template Package"
msgstr ""
-#: editor/editor_node.cpp editor/project_export.cpp
-msgid "Export Project"
-msgstr ""
-
#: editor/editor_node.cpp
msgid "Export Library"
msgstr ""
@@ -2931,10 +2943,6 @@ msgid "Merge With Existing"
msgstr ""
#: editor/editor_node.cpp
-msgid "Password:"
-msgstr ""
-
-#: editor/editor_node.cpp
msgid "Open & Run a Script"
msgstr ""
@@ -5496,6 +5504,21 @@ 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 ""
@@ -9112,6 +9135,10 @@ msgid "Export PCK/Zip"
msgstr ""
#: editor/project_export.cpp
+msgid "Export Project"
+msgstr ""
+
+#: editor/project_export.cpp
msgid "Export mode?"
msgstr ""
@@ -9202,10 +9229,6 @@ msgid "Couldn't create project.godot in project path."
msgstr ""
#: editor/project_manager.cpp
-msgid "The following files failed extraction from package:"
-msgstr ""
-
-#: editor/project_manager.cpp
msgid "Rename Project"
msgstr ""
@@ -10364,6 +10387,10 @@ msgid "Will load an existing script file."
msgstr ""
#: editor/script_create_dialog.cpp
+msgid "Script file already exists."
+msgstr ""
+
+#: editor/script_create_dialog.cpp
msgid "Class Name:"
msgstr ""
@@ -11889,7 +11916,14 @@ msgid "This node has been deprecated. Use AnimationTree instead."
msgstr ""
#: scene/gui/color_picker.cpp
-msgid "Pick a color from the screen."
+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
diff --git a/editor/translations/pl.po b/editor/translations/pl.po
index 4f18913a9b..25d7a396af 100644
--- a/editor/translations/pl.po
+++ b/editor/translations/pl.po
@@ -24,7 +24,7 @@
# Sebastian Pasich <sebastian.pasich@gmail.com>, 2017, 2019.
# siatek papieros <sbigneu@gmail.com>, 2016.
# Zatherz <zatherz@linux.pl>, 2017.
-# Tomek <kobewi4e@gmail.com>, 2018, 2019.
+# Tomek <kobewi4e@gmail.com>, 2018, 2019, 2020.
# Wojcieh Er Zet <wojcieh.rzepecki@gmail.com>, 2018.
# Dariusz Siek <dariuszynski@gmail.com>, 2018, 2019.
# Szymon Nowakowski <smnbdg13@gmail.com>, 2019.
@@ -42,7 +42,7 @@ msgid ""
msgstr ""
"Project-Id-Version: Godot Engine editor\n"
"POT-Creation-Date: \n"
-"PO-Revision-Date: 2019-12-26 00:02+0000\n"
+"PO-Revision-Date: 2020-01-03 21:21+0000\n"
"Last-Translator: Tomek <kobewi4e@gmail.com>\n"
"Language-Team: Polish <https://hosted.weblate.org/projects/godot-engine/"
"godot/pl/>\n"
@@ -455,7 +455,7 @@ msgstr "Nie da się dodać nowej ścieżki bez korzenia"
#: editor/animation_track_editor.cpp
msgid "Invalid track for Bezier (no suitable sub-properties)"
-msgstr ""
+msgstr "Nieprawidłowa ścieżka dla Beziera (brak odpowiednich podwłaściwości)"
#: editor/animation_track_editor.cpp
msgid "Add Bezier Track"
@@ -1223,10 +1223,24 @@ msgid "Error opening package file, not in ZIP format."
msgstr "BÅ‚Ä…d otwierania pliku pakietu, nie jest w formacie ZIP."
#: editor/editor_asset_installer.cpp
+#, fuzzy
+msgid "%s (Already Exists)"
+msgstr "Już istnieje"
+
+#: editor/editor_asset_installer.cpp
msgid "Uncompressing Assets"
msgstr "Dekompresja zasobów"
#: editor/editor_asset_installer.cpp editor/project_manager.cpp
+msgid "The following files failed extraction from package:"
+msgstr "Nie powiodło się wypakowanie z pakietu następujących plików:"
+
+#: editor/editor_asset_installer.cpp
+#, fuzzy
+msgid "And %s more files."
+msgstr "Pozostało %d plików"
+
+#: editor/editor_asset_installer.cpp editor/project_manager.cpp
msgid "Package installed successfully!"
msgstr "Pakiet zainstalowano poprawnie!"
@@ -1235,6 +1249,11 @@ msgstr "Pakiet zainstalowano poprawnie!"
msgid "Success!"
msgstr "Sukces!"
+#: editor/editor_asset_installer.cpp
+#, fuzzy
+msgid "Package Contents:"
+msgstr "Zawartość:"
+
#: editor/editor_asset_installer.cpp editor/editor_node.cpp
msgid "Install"
msgstr "Zainstaluj"
@@ -1373,6 +1392,11 @@ msgid "Invalid file, not an audio bus layout."
msgstr "Plik niepoprawny, nie jest układem magistral audio."
#: editor/editor_audio_buses.cpp
+#, fuzzy
+msgid "Error saving file: %s"
+msgstr "BÅ‚Ä…d zapisywania pliku!"
+
+#: editor/editor_audio_buses.cpp
msgid "Add Bus"
msgstr "Dodaj magistralÄ™"
@@ -2021,9 +2045,8 @@ msgid "Case Sensitive"
msgstr "Z uwzględnieniem wielkości liter"
#: editor/editor_help_search.cpp
-#, fuzzy
msgid "Show Hierarchy"
-msgstr "Pokaż linie pomocnicze"
+msgstr "Pokaż hierarchię"
#: editor/editor_help_search.cpp
msgid "Display All"
@@ -2062,9 +2085,8 @@ msgid "Class"
msgstr "Klasa"
#: editor/editor_help_search.cpp
-#, fuzzy
msgid "Method"
-msgstr "Metody"
+msgstr "Metoda"
#: editor/editor_help_search.cpp editor/plugins/script_text_editor.cpp
msgid "Signal"
@@ -2075,14 +2097,12 @@ msgid "Constant"
msgstr "Stałe"
#: editor/editor_help_search.cpp
-#, fuzzy
msgid "Property"
-msgstr "Właściwość:"
+msgstr "Właściwość"
#: editor/editor_help_search.cpp
-#, fuzzy
msgid "Theme Property"
-msgstr "Właściwości motywu"
+msgstr "Właściwość motywu"
#: editor/editor_inspector.cpp editor/project_settings_editor.cpp
msgid "Property:"
@@ -2165,10 +2185,6 @@ msgid "New Window"
msgstr "Nowe okno"
#: editor/editor_node.cpp
-msgid "Project export failed with error code %d."
-msgstr "Eksport projektu nie powiódł się, kod błędu to %d."
-
-#: editor/editor_node.cpp
msgid "Imported resources can't be saved."
msgstr "Zaimportowane zasoby nie mogą być zapisane."
@@ -3079,10 +3095,6 @@ msgstr "Zaimportuj Szablony z pliku ZIP"
msgid "Template Package"
msgstr "Szablonowy pakiet"
-#: editor/editor_node.cpp editor/project_export.cpp
-msgid "Export Project"
-msgstr "Wyeksportuj projekt"
-
#: editor/editor_node.cpp
msgid "Export Library"
msgstr "Wyeksportuj biblioteke"
@@ -3092,10 +3104,6 @@ msgid "Merge With Existing"
msgstr "Połącz z Istniejącym"
#: editor/editor_node.cpp
-msgid "Password:"
-msgstr "Hasło:"
-
-#: editor/editor_node.cpp
msgid "Open & Run a Script"
msgstr "Otwórz i Uruchom Skrypt"
@@ -3460,13 +3468,12 @@ msgid "Importing:"
msgstr "Importowanie:"
#: editor/export_template_manager.cpp
-#, fuzzy
msgid "Error getting the list of mirrors."
-msgstr "BÅ‚Ä…d przy eksporcie projektu!"
+msgstr "Błąd odbierania listy mirrorów."
#: editor/export_template_manager.cpp
msgid "Error parsing JSON of mirror list. Please report this issue!"
-msgstr ""
+msgstr "Błąd parsowania JSONa listy mirrorów. Zgłoś proszę ten błąd!"
#: editor/export_template_manager.cpp
msgid ""
@@ -4653,9 +4660,8 @@ msgid "Move Node"
msgstr "Przesuń węzeł"
#: editor/plugins/animation_state_machine_editor.cpp
-#, fuzzy
msgid "Transition exists!"
-msgstr "Przejście: "
+msgstr "Przejście istnieje!"
#: editor/plugins/animation_state_machine_editor.cpp
msgid "Add Transition"
@@ -5735,6 +5741,23 @@ msgstr "Maska emisji"
#: editor/plugins/cpu_particles_2d_editor_plugin.cpp
#: editor/plugins/particles_2d_editor_plugin.cpp
+#, fuzzy
+msgid "Solid Pixels"
+msgstr "Zmniejsz (piksele): "
+
+#: 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
+#, fuzzy
+msgid "Directed Border Pixels"
+msgstr "Katalogi i pliki:"
+
+#: editor/plugins/cpu_particles_2d_editor_plugin.cpp
+#: editor/plugins/particles_2d_editor_plugin.cpp
msgid "Capture from Pixel"
msgstr "Przechwytywanie z piksela"
@@ -5960,18 +5983,19 @@ msgstr "Rozmiar zarysu:"
#: editor/plugins/mesh_instance_editor_plugin.cpp
msgid "UV Channel Debug"
-msgstr ""
+msgstr "Debug kanału UV"
#: editor/plugins/mesh_library_editor_plugin.cpp
msgid "Remove item %d?"
msgstr "Usuń element %d?"
#: editor/plugins/mesh_library_editor_plugin.cpp
-#, fuzzy
msgid ""
"Update from existing scene?:\n"
"%s"
-msgstr "Aktualizuj ze sceny"
+msgstr ""
+"Zaktualizować z istniejącej sceny?:\n"
+"%s"
#: editor/plugins/mesh_library_editor_plugin.cpp
msgid "Mesh Library"
@@ -7520,9 +7544,8 @@ msgid "Create Mesh2D"
msgstr "Utwórz węzeł Mesh2D"
#: editor/plugins/sprite_editor_plugin.cpp
-#, fuzzy
msgid "Mesh2D Preview"
-msgstr "Tworzenie podglÄ…du Mesh"
+msgstr "PodglÄ…d Mesh2D"
#: editor/plugins/sprite_editor_plugin.cpp
msgid "Create Polygon2D"
@@ -7530,25 +7553,23 @@ msgstr "Utwórz węzeł Polygon2D"
#: editor/plugins/sprite_editor_plugin.cpp
msgid "Polygon2D Preview"
-msgstr ""
+msgstr "PodglÄ…d Polygon2D"
#: editor/plugins/sprite_editor_plugin.cpp
msgid "Create CollisionPolygon2D"
msgstr "Utwórz węzeł CollisionPolygon2D"
#: editor/plugins/sprite_editor_plugin.cpp
-#, fuzzy
msgid "CollisionPolygon2D Preview"
-msgstr "Utwórz węzeł CollisionPolygon2D"
+msgstr "PodglÄ…d CollisionPolygon2D"
#: editor/plugins/sprite_editor_plugin.cpp
msgid "Create LightOccluder2D"
msgstr "Utwórz węzeł LightOccluder2D"
#: editor/plugins/sprite_editor_plugin.cpp
-#, fuzzy
msgid "LightOccluder2D Preview"
-msgstr "Utwórz węzeł LightOccluder2D"
+msgstr "PodglÄ…d LightOccluder2D"
#: editor/plugins/sprite_editor_plugin.cpp
msgid "Sprite is empty!"
@@ -7628,9 +7649,8 @@ msgid "Add Frame"
msgstr "Dodaj klatkÄ™"
#: editor/plugins/sprite_frames_editor_plugin.cpp
-#, fuzzy
msgid "Unable to load images"
-msgstr "Nie można załadować obrazu:"
+msgstr "Nie można wczytać obrazków"
#: editor/plugins/sprite_frames_editor_plugin.cpp
msgid "ERROR: Couldn't load frame resource!"
@@ -8319,14 +8339,12 @@ msgid "Edit Tile Z Index"
msgstr "Edytuj indeks Z Kafelka"
#: editor/plugins/tile_set_editor_plugin.cpp
-#, fuzzy
msgid "Make Convex"
-msgstr "Zmień wielokąt na wypukły"
+msgstr "Uczyń wypukłym"
#: editor/plugins/tile_set_editor_plugin.cpp
-#, fuzzy
msgid "Make Concave"
-msgstr "Zmień wielokąt na wklęsły"
+msgstr "Uczyń wklęsłym"
#: editor/plugins/tile_set_editor_plugin.cpp
msgid "Create Collision Polygon"
@@ -9482,6 +9500,10 @@ msgid "Export PCK/Zip"
msgstr "Eksport PCK/Zip"
#: editor/project_export.cpp
+msgid "Export Project"
+msgstr "Wyeksportuj projekt"
+
+#: editor/project_export.cpp
msgid "Export mode?"
msgstr "Tryb eksportu?"
@@ -9575,10 +9597,6 @@ msgid "Couldn't create project.godot in project path."
msgstr "Nie można utworzyć project.godot w ścieżka projektu."
#: editor/project_manager.cpp
-msgid "The following files failed extraction from package:"
-msgstr "Nie powiodło się wypakowanie z pakietu następujących plików:"
-
-#: editor/project_manager.cpp
msgid "Rename Project"
msgstr "Zmień nazwę projektu"
@@ -10816,6 +10834,11 @@ msgid "Will load an existing script file."
msgstr "Wczytaj istniejÄ…cy plik skryptu."
#: editor/script_create_dialog.cpp
+#, fuzzy
+msgid "Script file already exists."
+msgstr "Podział już istnieje."
+
+#: editor/script_create_dialog.cpp
msgid "Class Name:"
msgstr "Nazwa klasy:"
@@ -11265,9 +11288,8 @@ msgid "Cursor Clear Rotation"
msgstr "Kursor Wyczyść obrót"
#: modules/gridmap/grid_map_editor_plugin.cpp
-#, fuzzy
msgid "Paste Selects"
-msgstr "Usuń zaznaczenie"
+msgstr "Wklejanie zaznacza"
#: modules/gridmap/grid_map_editor_plugin.cpp
msgid "Clear Selection"
@@ -12490,7 +12512,15 @@ msgid "This node has been deprecated. Use AnimationTree instead."
msgstr "Ten węzeł jest przestarzały. Zamiast tego użyj AnimationTree."
#: scene/gui/color_picker.cpp
-msgid "Pick a color from the screen."
+msgid ""
+"Color: #%s\n"
+"LMB: Set color\n"
+"RMB: Remove preset"
+msgstr ""
+
+#: scene/gui/color_picker.cpp
+#, fuzzy
+msgid "Pick a color from the editor window."
msgstr "Pobierz kolor z ekranu."
#: scene/gui/color_picker.cpp
@@ -12611,6 +12641,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 "Project export failed with error code %d."
+#~ msgstr "Eksport projektu nie powiódł się, kod błędu to %d."
+
+#~ msgid "Password:"
+#~ msgstr "Hasło:"
+
#~ msgid "Identifier segments must be of non-zero length."
#~ msgstr "Segmenty identyfikatora muszą mieć niezerową długość."
@@ -12939,9 +12975,6 @@ msgstr "Stałe nie mogą być modyfikowane."
#~ msgid "Create folder"
#~ msgstr "Utwórz katalog"
-#~ msgid "Already existing"
-#~ msgstr "Już istnieje"
-
#~ msgid "Custom Node"
#~ msgstr "Inny węzeł"
@@ -12990,9 +13023,6 @@ msgstr "Stałe nie mogą być modyfikowane."
#~ msgid "Split can't form an existing edge."
#~ msgstr "Podział nie może uformować istniejącej krawędzi."
-#~ msgid "Split already exists."
-#~ msgstr "Podział już istnieje."
-
#~ msgid "Add Split"
#~ msgstr "Dodaj podział"
diff --git a/editor/translations/pr.po b/editor/translations/pr.po
index 8f32df0402..b46588aa01 100644
--- a/editor/translations/pr.po
+++ b/editor/translations/pr.po
@@ -1197,10 +1197,22 @@ msgid "Error opening package file, not in ZIP format."
msgstr ""
#: editor/editor_asset_installer.cpp
+msgid "%s (Already Exists)"
+msgstr ""
+
+#: editor/editor_asset_installer.cpp
msgid "Uncompressing Assets"
msgstr ""
#: editor/editor_asset_installer.cpp editor/project_manager.cpp
+msgid "The following files failed extraction from package:"
+msgstr ""
+
+#: editor/editor_asset_installer.cpp
+msgid "And %s more files."
+msgstr ""
+
+#: editor/editor_asset_installer.cpp editor/project_manager.cpp
msgid "Package installed successfully!"
msgstr ""
@@ -1209,6 +1221,10 @@ msgstr ""
msgid "Success!"
msgstr ""
+#: editor/editor_asset_installer.cpp
+msgid "Package Contents:"
+msgstr ""
+
#: editor/editor_asset_installer.cpp editor/editor_node.cpp
msgid "Install"
msgstr ""
@@ -1351,6 +1367,11 @@ msgid "Invalid file, not an audio bus layout."
msgstr ""
#: editor/editor_audio_buses.cpp
+#, fuzzy
+msgid "Error saving file: %s"
+msgstr "Error loading yer Calligraphy Pen."
+
+#: editor/editor_audio_buses.cpp
msgid "Add Bus"
msgstr ""
@@ -2153,10 +2174,6 @@ msgid "New Window"
msgstr ""
#: editor/editor_node.cpp
-msgid "Project export failed with error code %d."
-msgstr ""
-
-#: editor/editor_node.cpp
msgid "Imported resources can't be saved."
msgstr ""
@@ -3010,10 +3027,6 @@ msgstr ""
msgid "Template Package"
msgstr "Discharge ye' Variable"
-#: editor/editor_node.cpp editor/project_export.cpp
-msgid "Export Project"
-msgstr ""
-
#: editor/editor_node.cpp
msgid "Export Library"
msgstr ""
@@ -3023,10 +3036,6 @@ msgid "Merge With Existing"
msgstr ""
#: editor/editor_node.cpp
-msgid "Password:"
-msgstr ""
-
-#: editor/editor_node.cpp
msgid "Open & Run a Script"
msgstr ""
@@ -5680,6 +5689,21 @@ 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 ""
@@ -9428,6 +9452,10 @@ msgid "Export PCK/Zip"
msgstr ""
#: editor/project_export.cpp
+msgid "Export Project"
+msgstr ""
+
+#: editor/project_export.cpp
msgid "Export mode?"
msgstr ""
@@ -9519,10 +9547,6 @@ msgid "Couldn't create project.godot in project path."
msgstr ""
#: editor/project_manager.cpp
-msgid "The following files failed extraction from package:"
-msgstr ""
-
-#: editor/project_manager.cpp
#, fuzzy
msgid "Rename Project"
msgstr "Rename Function"
@@ -10713,6 +10737,10 @@ msgid "Will load an existing script file."
msgstr ""
#: editor/script_create_dialog.cpp
+msgid "Script file already exists."
+msgstr ""
+
+#: editor/script_create_dialog.cpp
msgid "Class Name:"
msgstr ""
@@ -12314,7 +12342,14 @@ msgid "This node has been deprecated. Use AnimationTree instead."
msgstr ""
#: scene/gui/color_picker.cpp
-msgid "Pick a color from the screen."
+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
diff --git a/editor/translations/pt_BR.po b/editor/translations/pt_BR.po
index 9b681e11f7..212e1ceae1 100644
--- a/editor/translations/pt_BR.po
+++ b/editor/translations/pt_BR.po
@@ -76,12 +76,14 @@
# Nicolas Abril <nicolas.abril@protonmail.ch>, 2019.
# johnnybigoode <jamarson@gmail.com>, 2019.
# Zeero <igcdzeero@gmail.com>, 2019.
+# Gian Penna <gianfrancopen@gmail.com>, 2020.
+# sribgui <sribgui@gmail.com>, 2020.
msgid ""
msgstr ""
"Project-Id-Version: Godot Engine editor\n"
"POT-Creation-Date: 2016-05-30\n"
-"PO-Revision-Date: 2019-12-23 17:07+0000\n"
-"Last-Translator: Zeero <igcdzeero@gmail.com>\n"
+"PO-Revision-Date: 2020-01-03 21:21+0000\n"
+"Last-Translator: sribgui <sribgui@gmail.com>\n"
"Language-Team: Portuguese (Brazil) <https://hosted.weblate.org/projects/"
"godot-engine/godot/pt_BR/>\n"
"Language: pt_BR\n"
@@ -490,7 +492,7 @@ msgstr "Não é possível adicionar uma nova trilha sem uma raiz"
#: editor/animation_track_editor.cpp
msgid "Invalid track for Bezier (no suitable sub-properties)"
-msgstr ""
+msgstr "trajeto inválido para Bézier (sem subpropriedades adequadas)"
#: editor/animation_track_editor.cpp
msgid "Add Bezier Track"
@@ -1260,10 +1262,24 @@ msgid "Error opening package file, not in ZIP format."
msgstr "Erro ao abrir arquivo compactado, não está no formato ZIP."
#: editor/editor_asset_installer.cpp
+#, fuzzy
+msgid "%s (Already Exists)"
+msgstr "Já existe"
+
+#: editor/editor_asset_installer.cpp
msgid "Uncompressing Assets"
msgstr "Descompactando Assets"
#: editor/editor_asset_installer.cpp editor/project_manager.cpp
+msgid "The following files failed extraction from package:"
+msgstr "Os arquivos a seguir falharam ao serem extraídos do pacote:"
+
+#: editor/editor_asset_installer.cpp
+#, fuzzy
+msgid "And %s more files."
+msgstr "%d mais arquivo(s)"
+
+#: editor/editor_asset_installer.cpp editor/project_manager.cpp
msgid "Package installed successfully!"
msgstr "Pacote instalado com sucesso!"
@@ -1272,6 +1288,11 @@ msgstr "Pacote instalado com sucesso!"
msgid "Success!"
msgstr "Sucesso!"
+#: editor/editor_asset_installer.cpp
+#, fuzzy
+msgid "Package Contents:"
+msgstr "Conteúdo:"
+
#: editor/editor_asset_installer.cpp editor/editor_node.cpp
msgid "Install"
msgstr "Instalar"
@@ -1410,6 +1431,11 @@ msgid "Invalid file, not an audio bus layout."
msgstr "Arquivo inválido, não é um layout de canais de áudio."
#: editor/editor_audio_buses.cpp
+#, fuzzy
+msgid "Error saving file: %s"
+msgstr "Erro ao salvar o arquivo!"
+
+#: editor/editor_audio_buses.cpp
msgid "Add Bus"
msgstr "Adicionar Canal"
@@ -2060,9 +2086,8 @@ msgid "Case Sensitive"
msgstr "Diferenciar Caixa"
#: editor/editor_help_search.cpp
-#, fuzzy
msgid "Show Hierarchy"
-msgstr "Mostrar auxiliadores"
+msgstr "Mostrar Hierarquia"
#: editor/editor_help_search.cpp
msgid "Display All"
@@ -2101,9 +2126,8 @@ msgid "Class"
msgstr "Classe"
#: editor/editor_help_search.cpp
-#, fuzzy
msgid "Method"
-msgstr "Métodos"
+msgstr "Método"
#: editor/editor_help_search.cpp editor/plugins/script_text_editor.cpp
msgid "Signal"
@@ -2114,12 +2138,10 @@ msgid "Constant"
msgstr "Constante"
#: editor/editor_help_search.cpp
-#, fuzzy
msgid "Property"
-msgstr "Propriedade:"
+msgstr "Propriedade"
#: editor/editor_help_search.cpp
-#, fuzzy
msgid "Theme Property"
msgstr "Propriedades do Tema"
@@ -2204,10 +2226,6 @@ msgid "New Window"
msgstr "Nova Janela"
#: editor/editor_node.cpp
-msgid "Project export failed with error code %d."
-msgstr "Falha na exportação do projeto com código de erro %d."
-
-#: editor/editor_node.cpp
msgid "Imported resources can't be saved."
msgstr "Recursos Importados não podem ser salvos."
@@ -3127,10 +3145,6 @@ msgstr "Importar Modelos de um Arquivo ZIP"
msgid "Template Package"
msgstr "Pacote de modelos"
-#: editor/editor_node.cpp editor/project_export.cpp
-msgid "Export Project"
-msgstr "Exportar Projeto"
-
#: editor/editor_node.cpp
msgid "Export Library"
msgstr "Exportar Biblioteca"
@@ -3140,10 +3154,6 @@ msgid "Merge With Existing"
msgstr "Fundir Com Existente"
#: editor/editor_node.cpp
-msgid "Password:"
-msgstr "Senha:"
-
-#: editor/editor_node.cpp
msgid "Open & Run a Script"
msgstr "Abrir e Rodar um Script"
@@ -3509,13 +3519,14 @@ msgid "Importing:"
msgstr "Importando:"
#: editor/export_template_manager.cpp
-#, fuzzy
msgid "Error getting the list of mirrors."
-msgstr "Erro ao escrever o PCK do projeto!"
+msgstr "Erro ao obter a lista de espelhos."
#: editor/export_template_manager.cpp
msgid "Error parsing JSON of mirror list. Please report this issue!"
msgstr ""
+"Erro ao analisar o JSON da lista de espelhos. Por favor, reporte este "
+"problema!"
#: editor/export_template_manager.cpp
msgid ""
@@ -4705,9 +4716,8 @@ msgid "Move Node"
msgstr "Mover Nó"
#: editor/plugins/animation_state_machine_editor.cpp
-#, fuzzy
msgid "Transition exists!"
-msgstr "Transições"
+msgstr "A transição já existe!"
#: editor/plugins/animation_state_machine_editor.cpp
msgid "Add Transition"
@@ -5785,6 +5795,23 @@ msgstr "Máscara de Emissão"
#: editor/plugins/cpu_particles_2d_editor_plugin.cpp
#: editor/plugins/particles_2d_editor_plugin.cpp
+#, fuzzy
+msgid "Solid Pixels"
+msgstr "Diminuir (Pixels): "
+
+#: 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
+#, fuzzy
+msgid "Directed Border Pixels"
+msgstr "Diretórios & Arquivos:"
+
+#: editor/plugins/cpu_particles_2d_editor_plugin.cpp
+#: editor/plugins/particles_2d_editor_plugin.cpp
msgid "Capture from Pixel"
msgstr "Capturar a partir do Pixel"
@@ -6010,18 +6037,19 @@ msgstr "Tamanho do Contorno:"
#: editor/plugins/mesh_instance_editor_plugin.cpp
msgid "UV Channel Debug"
-msgstr ""
+msgstr "Depuração do Canal UV"
#: editor/plugins/mesh_library_editor_plugin.cpp
msgid "Remove item %d?"
msgstr "Remover item %d?"
#: editor/plugins/mesh_library_editor_plugin.cpp
-#, fuzzy
msgid ""
"Update from existing scene?:\n"
"%s"
-msgstr "Atualizar a partir de Cena"
+msgstr ""
+"Atualizar a partir da cena existente?:\n"
+"%s"
#: editor/plugins/mesh_library_editor_plugin.cpp
msgid "Mesh Library"
@@ -7573,35 +7601,32 @@ msgid "Create Mesh2D"
msgstr "Crie uma Malha2D"
#: editor/plugins/sprite_editor_plugin.cpp
-#, fuzzy
msgid "Mesh2D Preview"
-msgstr "Criando Previsualizações das Malhas"
+msgstr "Visualizar Malha2D"
#: editor/plugins/sprite_editor_plugin.cpp
msgid "Create Polygon2D"
-msgstr "Criar Polígono3D"
+msgstr "Criar Polígono2D"
#: editor/plugins/sprite_editor_plugin.cpp
msgid "Polygon2D Preview"
-msgstr ""
+msgstr "Visualizar Polígono2D"
#: editor/plugins/sprite_editor_plugin.cpp
msgid "Create CollisionPolygon2D"
msgstr "Criar PolígonoDeColisão2D"
#: editor/plugins/sprite_editor_plugin.cpp
-#, fuzzy
msgid "CollisionPolygon2D Preview"
-msgstr "Criar PolígonoDeColisão2D"
+msgstr "Visualizar Polígono De Colisão 2D"
#: editor/plugins/sprite_editor_plugin.cpp
msgid "Create LightOccluder2D"
msgstr "Criar OclusorDeLuz2D"
#: editor/plugins/sprite_editor_plugin.cpp
-#, fuzzy
msgid "LightOccluder2D Preview"
-msgstr "Criar OclusorDeLuz2D"
+msgstr "visualizar Oclusor De Luz 2D"
#: editor/plugins/sprite_editor_plugin.cpp
msgid "Sprite is empty!"
@@ -7681,9 +7706,8 @@ msgid "Add Frame"
msgstr "Adicionar Frame"
#: editor/plugins/sprite_frames_editor_plugin.cpp
-#, fuzzy
msgid "Unable to load images"
-msgstr "Não se pôde carregar imagem:"
+msgstr "Não foi possível carregar a imagem"
#: editor/plugins/sprite_frames_editor_plugin.cpp
msgid "ERROR: Couldn't load frame resource!"
@@ -8370,14 +8394,12 @@ msgid "Edit Tile Z Index"
msgstr "Editar índice de telha Z"
#: editor/plugins/tile_set_editor_plugin.cpp
-#, fuzzy
msgid "Make Convex"
msgstr "Tornar o Polígono Convexo"
#: editor/plugins/tile_set_editor_plugin.cpp
-#, fuzzy
msgid "Make Concave"
-msgstr "Tornar o Polígono Côncavo"
+msgstr "tornar Côncavo"
#: editor/plugins/tile_set_editor_plugin.cpp
msgid "Create Collision Polygon"
@@ -9533,6 +9555,10 @@ msgid "Export PCK/Zip"
msgstr "Exportar PCK/Zip"
#: editor/project_export.cpp
+msgid "Export Project"
+msgstr "Exportar Projeto"
+
+#: editor/project_export.cpp
msgid "Export mode?"
msgstr "Modo de exportação?"
@@ -9626,10 +9652,6 @@ msgid "Couldn't create project.godot in project path."
msgstr "Não foi possível criar project.godot no caminho do projeto."
#: editor/project_manager.cpp
-msgid "The following files failed extraction from package:"
-msgstr "Os arquivos a seguir falharam ao serem extraídos do pacote:"
-
-#: editor/project_manager.cpp
msgid "Rename Project"
msgstr "Renomear Projeto"
@@ -10867,6 +10889,11 @@ msgid "Will load an existing script file."
msgstr "Carregará arquivo de script existente."
#: editor/script_create_dialog.cpp
+#, fuzzy
+msgid "Script file already exists."
+msgstr "A ação \"%s\" já existe!"
+
+#: editor/script_create_dialog.cpp
msgid "Class Name:"
msgstr "Nome da Classe:"
@@ -11317,9 +11344,8 @@ msgid "Cursor Clear Rotation"
msgstr "Limpar Rotação do Cursor"
#: modules/gridmap/grid_map_editor_plugin.cpp
-#, fuzzy
msgid "Paste Selects"
-msgstr "Apagar Seleção"
+msgstr "Colar Selecionados"
#: modules/gridmap/grid_map_editor_plugin.cpp
msgid "Clear Selection"
@@ -12539,7 +12565,15 @@ msgid "This node has been deprecated. Use AnimationTree instead."
msgstr "Este nó foi reprovado. Use AnimationTree em vez disso."
#: scene/gui/color_picker.cpp
-msgid "Pick a color from the screen."
+msgid ""
+"Color: #%s\n"
+"LMB: Set color\n"
+"RMB: Remove preset"
+msgstr ""
+
+#: scene/gui/color_picker.cpp
+#, fuzzy
+msgid "Pick a color from the editor window."
msgstr "Escolha uma cor da tela."
#: scene/gui/color_picker.cpp
@@ -12662,6 +12696,12 @@ 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 "Project export failed with error code %d."
+#~ msgstr "Falha na exportação do projeto com código de erro %d."
+
+#~ msgid "Password:"
+#~ msgstr "Senha:"
+
#~ msgid "Identifier segments must be of non-zero length."
#~ msgstr "Segmentos identificadores devem ter comprimento diferente de zero."
@@ -12956,9 +12996,6 @@ msgstr "Constantes não podem serem modificadas."
#~ msgid "Create folder"
#~ msgstr "Criar Pasta"
-#~ msgid "Already existing"
-#~ msgstr "Já existe"
-
#~ msgid "Custom Node"
#~ msgstr "Nó personalizado"
@@ -13003,10 +13040,6 @@ msgstr "Constantes não podem serem modificadas."
#~ "OrientedPathFollow só funciona quando definido como filho de um nó Path."
#, fuzzy
-#~ msgid "Split already exists."
-#~ msgstr "A ação \"%s\" já existe!"
-
-#, fuzzy
#~ msgid "Add Split"
#~ msgstr "Adicionar ponto"
diff --git a/editor/translations/pt_PT.po b/editor/translations/pt_PT.po
index d134b16ca8..f0728bd81d 100644
--- a/editor/translations/pt_PT.po
+++ b/editor/translations/pt_PT.po
@@ -6,7 +6,7 @@
# Carlos Vieira <carlos.vieira@gmail.com>, 2017.
# João <joao@nogordio.com>, 2018.
# João Graça <jgraca95@gmail.com>, 2017.
-# João Lopes <linux-man@hotmail.com>, 2017-2018, 2019.
+# João Lopes <linux-man@hotmail.com>, 2017-2018, 2019, 2020.
# Miguel Gomes <miggas09@gmail.com>, 2017.
# Paulo Caldeira <paucal@gmail.com>, 2018.
# Pedro Gomes <pedrogomes1698@gmail.com>, 2017.
@@ -19,7 +19,7 @@ msgid ""
msgstr ""
"Project-Id-Version: Godot Engine editor\n"
"POT-Creation-Date: \n"
-"PO-Revision-Date: 2019-12-23 17:08+0000\n"
+"PO-Revision-Date: 2020-01-03 21:21+0000\n"
"Last-Translator: João Lopes <linux-man@hotmail.com>\n"
"Language-Team: Portuguese (Portugal) <https://hosted.weblate.org/projects/"
"godot-engine/godot/pt_PT/>\n"
@@ -432,7 +432,7 @@ msgstr "Não é possível adicionar nova pista sem uma raíz"
#: editor/animation_track_editor.cpp
msgid "Invalid track for Bezier (no suitable sub-properties)"
-msgstr ""
+msgstr "Faixa inválida para Bezier (sub-propriedades não apropriadas)"
#: editor/animation_track_editor.cpp
msgid "Add Bezier Track"
@@ -1202,10 +1202,24 @@ msgid "Error opening package file, not in ZIP format."
msgstr "Erro ao abrir ficheiro comprimido, não está no formato ZIP."
#: editor/editor_asset_installer.cpp
+#, fuzzy
+msgid "%s (Already Exists)"
+msgstr "Já existe"
+
+#: editor/editor_asset_installer.cpp
msgid "Uncompressing Assets"
msgstr "A descompactar Ativos"
#: editor/editor_asset_installer.cpp editor/project_manager.cpp
+msgid "The following files failed extraction from package:"
+msgstr "Falhou a extração dos seguintes Ficheiros do pacote:"
+
+#: editor/editor_asset_installer.cpp
+#, fuzzy
+msgid "And %s more files."
+msgstr "%d mais Ficheiros"
+
+#: editor/editor_asset_installer.cpp editor/project_manager.cpp
msgid "Package installed successfully!"
msgstr "Pacote Instalado com sucesso!"
@@ -1214,6 +1228,11 @@ msgstr "Pacote Instalado com sucesso!"
msgid "Success!"
msgstr "Sucesso!"
+#: editor/editor_asset_installer.cpp
+#, fuzzy
+msgid "Package Contents:"
+msgstr "Conteúdos:"
+
#: editor/editor_asset_installer.cpp editor/editor_node.cpp
msgid "Install"
msgstr "Instalar"
@@ -1352,6 +1371,11 @@ msgid "Invalid file, not an audio bus layout."
msgstr "Ficheiro inválido, não é um Modelo válido de barramento de áudio."
#: editor/editor_audio_buses.cpp
+#, fuzzy
+msgid "Error saving file: %s"
+msgstr "Erro ao guardar ficheiro!"
+
+#: editor/editor_audio_buses.cpp
msgid "Add Bus"
msgstr "Adicionar Barramento"
@@ -1881,7 +1905,7 @@ msgstr "Diretorias e Ficheiros:"
#: editor/plugins/style_box_editor_plugin.cpp
#: editor/plugins/theme_editor_plugin.cpp
msgid "Preview:"
-msgstr "Visualização prévia:"
+msgstr "Pré-visualização:"
#: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp
msgid "File:"
@@ -2004,9 +2028,8 @@ msgid "Case Sensitive"
msgstr "Sensível a maiúsculas"
#: editor/editor_help_search.cpp
-#, fuzzy
msgid "Show Hierarchy"
-msgstr "Mostrar ajudantes"
+msgstr "Mostrar Hierarquia"
#: editor/editor_help_search.cpp
msgid "Display All"
@@ -2045,9 +2068,8 @@ msgid "Class"
msgstr "Classe"
#: editor/editor_help_search.cpp
-#, fuzzy
msgid "Method"
-msgstr "Métodos"
+msgstr "Método"
#: editor/editor_help_search.cpp editor/plugins/script_text_editor.cpp
msgid "Signal"
@@ -2058,14 +2080,12 @@ msgid "Constant"
msgstr "Constante"
#: editor/editor_help_search.cpp
-#, fuzzy
msgid "Property"
-msgstr "Propriedade:"
+msgstr "Propriedade"
#: editor/editor_help_search.cpp
-#, fuzzy
msgid "Theme Property"
-msgstr "Propriedades do Tema"
+msgstr "Propriedade do Tema"
#: editor/editor_inspector.cpp editor/project_settings_editor.cpp
msgid "Property:"
@@ -2148,10 +2168,6 @@ msgid "New Window"
msgstr "Nova Janela"
#: editor/editor_node.cpp
-msgid "Project export failed with error code %d."
-msgstr "Exportação do projeto falhou com código de erro %d."
-
-#: editor/editor_node.cpp
msgid "Imported resources can't be saved."
msgstr "Recursos importados não podem ser guardados."
@@ -3068,10 +3084,6 @@ msgstr "Importar Modelos a partir de um Ficheiro ZIP"
msgid "Template Package"
msgstr "Pacote de Modelo"
-#: editor/editor_node.cpp editor/project_export.cpp
-msgid "Export Project"
-msgstr "Exportar Projeto"
-
#: editor/editor_node.cpp
msgid "Export Library"
msgstr "Exportar Biblioteca"
@@ -3081,10 +3093,6 @@ msgid "Merge With Existing"
msgstr "Fundir com o Existente"
#: editor/editor_node.cpp
-msgid "Password:"
-msgstr "Senha:"
-
-#: editor/editor_node.cpp
msgid "Open & Run a Script"
msgstr "Abrir & Executar um Script"
@@ -3449,11 +3457,12 @@ msgstr "A Importar:"
#: editor/export_template_manager.cpp
msgid "Error getting the list of mirrors."
-msgstr ""
+msgstr "Erro na receção da lista de mirrors."
#: editor/export_template_manager.cpp
msgid "Error parsing JSON of mirror list. Please report this issue!"
msgstr ""
+"Erro ao analisar a lista de mirrors JSON. Por favor comunique o problema!"
#: editor/export_template_manager.cpp
msgid ""
@@ -4638,9 +4647,8 @@ msgid "Move Node"
msgstr "Mover Nó"
#: editor/plugins/animation_state_machine_editor.cpp
-#, fuzzy
msgid "Transition exists!"
-msgstr "Transição: "
+msgstr "Transição existe!"
#: editor/plugins/animation_state_machine_editor.cpp
msgid "Add Transition"
@@ -5101,7 +5109,7 @@ msgstr "Consolidar Lightmaps"
#: editor/plugins/camera_editor_plugin.cpp
#: editor/plugins/spatial_editor_plugin.cpp editor/rename_dialog.cpp
msgid "Preview"
-msgstr "Previsualização"
+msgstr "Pré-visualização"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Configure Snap"
@@ -5713,6 +5721,23 @@ msgstr "Máscara de Emissão"
#: editor/plugins/cpu_particles_2d_editor_plugin.cpp
#: editor/plugins/particles_2d_editor_plugin.cpp
+#, fuzzy
+msgid "Solid Pixels"
+msgstr "Encolher (Pixeis): "
+
+#: 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
+#, fuzzy
+msgid "Directed Border Pixels"
+msgstr "Diretorias e Ficheiros:"
+
+#: editor/plugins/cpu_particles_2d_editor_plugin.cpp
+#: editor/plugins/particles_2d_editor_plugin.cpp
msgid "Capture from Pixel"
msgstr "Capturar a partir do pixel"
@@ -5938,18 +5963,19 @@ msgstr "Tamanho do contorno:"
#: editor/plugins/mesh_instance_editor_plugin.cpp
msgid "UV Channel Debug"
-msgstr ""
+msgstr "Debug Canal UV"
#: editor/plugins/mesh_library_editor_plugin.cpp
msgid "Remove item %d?"
msgstr "Remover item %d?"
#: editor/plugins/mesh_library_editor_plugin.cpp
-#, fuzzy
msgid ""
"Update from existing scene?:\n"
"%s"
-msgstr "Atualizar da Cena"
+msgstr ""
+"Atualizar a partir da cena existente?:\n"
+"%s"
#: editor/plugins/mesh_library_editor_plugin.cpp
msgid "Mesh Library"
@@ -7252,7 +7278,7 @@ msgstr "Ativar Doppler"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Cinematic Preview"
-msgstr "Previsualização cinemática"
+msgstr "Pré-visualização Cinemática"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Freelook Left"
@@ -7495,9 +7521,8 @@ msgid "Create Mesh2D"
msgstr "Criar Mesh2D"
#: editor/plugins/sprite_editor_plugin.cpp
-#, fuzzy
msgid "Mesh2D Preview"
-msgstr "A criar pré-visualizações de Malha"
+msgstr "Pré-visualização Mesh2D"
#: editor/plugins/sprite_editor_plugin.cpp
msgid "Create Polygon2D"
@@ -7505,25 +7530,23 @@ msgstr "Criar Polygon2D"
#: editor/plugins/sprite_editor_plugin.cpp
msgid "Polygon2D Preview"
-msgstr ""
+msgstr "Pré-visualização Polygon2D"
#: editor/plugins/sprite_editor_plugin.cpp
msgid "Create CollisionPolygon2D"
msgstr "Criar CollisionPolygon2D"
#: editor/plugins/sprite_editor_plugin.cpp
-#, fuzzy
msgid "CollisionPolygon2D Preview"
-msgstr "Criar CollisionPolygon2D"
+msgstr "Pré-visualização CollisionPolygon2D"
#: editor/plugins/sprite_editor_plugin.cpp
msgid "Create LightOccluder2D"
msgstr "Criar LightOccluder2D"
#: editor/plugins/sprite_editor_plugin.cpp
-#, fuzzy
msgid "LightOccluder2D Preview"
-msgstr "Criar LightOccluder2D"
+msgstr "Pré-visualização LightOccluder2D"
#: editor/plugins/sprite_editor_plugin.cpp
msgid "Sprite is empty!"
@@ -7583,7 +7606,7 @@ msgstr "Crescer (Pixeis): "
#: editor/plugins/sprite_editor_plugin.cpp
msgid "Update Preview"
-msgstr "Atualizar Previsualização"
+msgstr "Atualizar Pré-visualização"
#: editor/plugins/sprite_editor_plugin.cpp
msgid "Settings:"
@@ -7602,9 +7625,8 @@ msgid "Add Frame"
msgstr "Adicionar Frame"
#: editor/plugins/sprite_frames_editor_plugin.cpp
-#, fuzzy
msgid "Unable to load images"
-msgstr "Falha ao carregar recurso."
+msgstr "Incapaz de carregar imagens"
#: editor/plugins/sprite_frames_editor_plugin.cpp
msgid "ERROR: Couldn't load frame resource!"
@@ -8292,14 +8314,12 @@ msgid "Edit Tile Z Index"
msgstr "Editar Ãndice Z de Tile"
#: editor/plugins/tile_set_editor_plugin.cpp
-#, fuzzy
msgid "Make Convex"
-msgstr "Fazer Polígono Convexo"
+msgstr "Fazer Convexo"
#: editor/plugins/tile_set_editor_plugin.cpp
-#, fuzzy
msgid "Make Concave"
-msgstr "Fazer Polígono Côncavo"
+msgstr "Fazer Côncavo"
#: editor/plugins/tile_set_editor_plugin.cpp
msgid "Create Collision Polygon"
@@ -9450,6 +9470,10 @@ msgid "Export PCK/Zip"
msgstr "Exportar PCK/Zip"
#: editor/project_export.cpp
+msgid "Export Project"
+msgstr "Exportar Projeto"
+
+#: editor/project_export.cpp
msgid "Export mode?"
msgstr "Modo Exportação?"
@@ -9543,10 +9567,6 @@ msgid "Couldn't create project.godot in project path."
msgstr "Impossível criar project.godot no Caminho do Projeto."
#: editor/project_manager.cpp
-msgid "The following files failed extraction from package:"
-msgstr "Falhou a extração dos seguintes Ficheiros do pacote:"
-
-#: editor/project_manager.cpp
msgid "Rename Project"
msgstr "Renomear Projeto"
@@ -10782,6 +10802,11 @@ msgid "Will load an existing script file."
msgstr "Vai carregar ficheiro de script existente."
#: editor/script_create_dialog.cpp
+#, fuzzy
+msgid "Script file already exists."
+msgstr "Separação já existe."
+
+#: editor/script_create_dialog.cpp
msgid "Class Name:"
msgstr "Nome de Classe:"
@@ -11232,9 +11257,8 @@ msgid "Cursor Clear Rotation"
msgstr "Limpar rotação do Cursor"
#: modules/gridmap/grid_map_editor_plugin.cpp
-#, fuzzy
msgid "Paste Selects"
-msgstr "Apagar seleção"
+msgstr "Colar Seleção"
#: modules/gridmap/grid_map_editor_plugin.cpp
msgid "Clear Selection"
@@ -12451,7 +12475,15 @@ msgid "This node has been deprecated. Use AnimationTree instead."
msgstr "Este nó foi depreciado. Use AnimationTree em vez disso."
#: scene/gui/color_picker.cpp
-msgid "Pick a color from the screen."
+msgid ""
+"Color: #%s\n"
+"LMB: Set color\n"
+"RMB: Remove preset"
+msgstr ""
+
+#: scene/gui/color_picker.cpp
+#, fuzzy
+msgid "Pick a color from the editor window."
msgstr "Escolha uma cor do ecrã."
#: scene/gui/color_picker.cpp
@@ -12547,7 +12579,7 @@ msgstr ""
#: scene/resources/visual_shader_nodes.cpp
msgid "Invalid source for preview."
-msgstr "Fonte inválida para previsualização."
+msgstr "Fonte inválida para pré-visualização."
#: scene/resources/visual_shader_nodes.cpp
msgid "Invalid source for shader."
@@ -12573,6 +12605,12 @@ 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 "Project export failed with error code %d."
+#~ msgstr "Exportação do projeto falhou com código de erro %d."
+
+#~ msgid "Password:"
+#~ msgstr "Senha:"
+
#~ msgid "Identifier segments must be of non-zero length."
#~ msgstr ""
#~ "Identificador de segmentos devem ser de comprimento diferente de zero."
@@ -13048,9 +13086,6 @@ msgstr "Constantes não podem ser modificadas."
#~ msgid "Create folder"
#~ msgstr "Criar pasta"
-#~ msgid "Already existing"
-#~ msgstr "Já existe"
-
#~ msgid "Custom Node"
#~ msgstr "Nó Personalizado"
@@ -13102,9 +13137,6 @@ msgstr "Constantes não podem ser modificadas."
#~ msgid "Split can't form an existing edge."
#~ msgstr "Separação não forma uma aresta existente."
-#~ msgid "Split already exists."
-#~ msgstr "Separação já existe."
-
#~ msgid "Add Split"
#~ msgstr "Adicionar Separação"
diff --git a/editor/translations/ro.po b/editor/translations/ro.po
index 02886b9b34..6625e3a8b4 100644
--- a/editor/translations/ro.po
+++ b/editor/translations/ro.po
@@ -1241,10 +1241,24 @@ msgid "Error opening package file, not in ZIP format."
msgstr "Eroare la deschiderea fişierului pachet, nu este în format zip."
#: editor/editor_asset_installer.cpp
+#, fuzzy
+msgid "%s (Already Exists)"
+msgstr "AutoLoad '%s' există deja!"
+
+#: editor/editor_asset_installer.cpp
msgid "Uncompressing Assets"
msgstr "Decomprimare Asset-uri"
#: editor/editor_asset_installer.cpp editor/project_manager.cpp
+msgid "The following files failed extraction from package:"
+msgstr ""
+
+#: editor/editor_asset_installer.cpp
+#, fuzzy
+msgid "And %s more files."
+msgstr "%d mai multe fișiere"
+
+#: editor/editor_asset_installer.cpp editor/project_manager.cpp
#, fuzzy
msgid "Package installed successfully!"
msgstr "Pachet Instalat cu Succes!"
@@ -1254,6 +1268,11 @@ msgstr "Pachet Instalat cu Succes!"
msgid "Success!"
msgstr "Succes!"
+#: editor/editor_asset_installer.cpp
+#, fuzzy
+msgid "Package Contents:"
+msgstr "Conținut:"
+
#: editor/editor_asset_installer.cpp editor/editor_node.cpp
msgid "Install"
msgstr "Instalați"
@@ -1393,6 +1412,11 @@ msgid "Invalid file, not an audio bus layout."
msgstr "Fişier nevalid, nu este o schemă de pistă audio."
#: editor/editor_audio_buses.cpp
+#, fuzzy
+msgid "Error saving file: %s"
+msgstr "Eroare la salvarea TileSet!"
+
+#: editor/editor_audio_buses.cpp
msgid "Add Bus"
msgstr "Adaugați Pistă Audio"
@@ -2246,10 +2270,6 @@ msgid "New Window"
msgstr ""
#: editor/editor_node.cpp
-msgid "Project export failed with error code %d."
-msgstr "Exportul de proiect nu a reuÅŸit cu un cod de eroare %d."
-
-#: editor/editor_node.cpp
msgid "Imported resources can't be saved."
msgstr ""
@@ -3185,10 +3205,6 @@ msgstr "Importă Șabloane Dintr-o Arhivă ZIP"
msgid "Template Package"
msgstr "Exportă Managerul de Șabloane"
-#: editor/editor_node.cpp editor/project_export.cpp
-msgid "Export Project"
-msgstr "Exportă Proiectul"
-
#: editor/editor_node.cpp
msgid "Export Library"
msgstr "Exportă Librăria"
@@ -3198,10 +3214,6 @@ msgid "Merge With Existing"
msgstr "Contopește Cu Existentul"
#: editor/editor_node.cpp
-msgid "Password:"
-msgstr "Parola:"
-
-#: editor/editor_node.cpp
msgid "Open & Run a Script"
msgstr "Deschide și Execută un Script"
@@ -5981,6 +5993,22 @@ msgstr "Mască de Emisie"
#: 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
+#, fuzzy
+msgid "Directed Border Pixels"
+msgstr "Directoare și Fişiere:"
+
+#: editor/plugins/cpu_particles_2d_editor_plugin.cpp
+#: editor/plugins/particles_2d_editor_plugin.cpp
msgid "Capture from Pixel"
msgstr "Capturare din Pixel"
@@ -9820,6 +9848,10 @@ msgid "Export PCK/Zip"
msgstr ""
#: editor/project_export.cpp
+msgid "Export Project"
+msgstr "Exportă Proiectul"
+
+#: editor/project_export.cpp
#, fuzzy
msgid "Export mode?"
msgstr "Exportă Proiectul"
@@ -9913,10 +9945,6 @@ msgid "Couldn't create project.godot in project path."
msgstr ""
#: editor/project_manager.cpp
-msgid "The following files failed extraction from package:"
-msgstr ""
-
-#: editor/project_manager.cpp
msgid "Rename Project"
msgstr ""
@@ -11137,6 +11165,11 @@ msgstr "Încărcaţi o Schemă de Pistă Audio existentă."
#: editor/script_create_dialog.cpp
#, fuzzy
+msgid "Script file already exists."
+msgstr "AutoLoad '%s' există deja!"
+
+#: editor/script_create_dialog.cpp
+#, fuzzy
msgid "Class Name:"
msgstr "Clasă:"
@@ -12721,7 +12754,14 @@ msgid "This node has been deprecated. Use AnimationTree instead."
msgstr ""
#: scene/gui/color_picker.cpp
-msgid "Pick a color from the screen."
+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
@@ -12825,6 +12865,12 @@ msgstr ""
msgid "Constants cannot be modified."
msgstr ""
+#~ msgid "Project export failed with error code %d."
+#~ msgstr "Exportul de proiect nu a reuÅŸit cu un cod de eroare %d."
+
+#~ msgid "Password:"
+#~ msgstr "Parola:"
+
#~ msgid "Pause the scene"
#~ msgstr "ÃŽntrerupe scena"
@@ -12996,10 +13042,6 @@ msgstr ""
#~ msgstr "Col:"
#, fuzzy
-#~ msgid "Split already exists."
-#~ msgstr "AutoLoad '%s' există deja!"
-
-#, fuzzy
#~ msgid "Add Split"
#~ msgstr "Adaugă punct"
diff --git a/editor/translations/ru.po b/editor/translations/ru.po
index d865d8b829..67e54e0a3b 100644
--- a/editor/translations/ru.po
+++ b/editor/translations/ru.po
@@ -51,7 +51,7 @@
# Teashrock <kajitsu22@gmail.com>, 2019.
# Дмитрий Ефимов <daefimov@gmail.com>, 2019.
# Sergey <www.window1@mail.ru>, 2019.
-# Vladislav <onion.ring@mail.ru>, 2019.
+# Vladislav <onion.ring@mail.ru>, 2019, 2020.
# knightpp <kotteam99@gmail.com>, 2019.
# КонÑтантин Рин <email.to.rean@gmail.com>, 2019.
# Maxim Samburskiy <alpacones@outlook.com>, 2019.
@@ -65,8 +65,8 @@ msgid ""
msgstr ""
"Project-Id-Version: Godot Engine editor\n"
"POT-Creation-Date: \n"
-"PO-Revision-Date: 2019-12-22 04:19+0000\n"
-"Last-Translator: Vitaly <arkology11@gmail.com>\n"
+"PO-Revision-Date: 2020-01-03 21:21+0000\n"
+"Last-Translator: Vladislav <onion.ring@mail.ru>\n"
"Language-Team: Russian <https://hosted.weblate.org/projects/godot-engine/"
"godot/ru/>\n"
"Language: ru\n"
@@ -475,8 +475,9 @@ msgid "Not possible to add a new track without a root"
msgstr "ÐÐµÐ»ÑŒÐ·Ñ Ð´Ð¾Ð±Ð°Ð²Ð¸Ñ‚ÑŒ новый трек без корневого узла"
#: editor/animation_track_editor.cpp
+#, fuzzy
msgid "Invalid track for Bezier (no suitable sub-properties)"
-msgstr ""
+msgstr "Ðеверный трек Ð´Ð»Ñ ÐºÑ€Ð¸Ð²Ð¾Ð¹ Безье (нет подходÑщих подÑвойÑтв)"
#: editor/animation_track_editor.cpp
msgid "Add Bezier Track"
@@ -1248,10 +1249,24 @@ msgid "Error opening package file, not in ZIP format."
msgstr "Ошибка при открытии файла пакета, не в формате zip."
#: editor/editor_asset_installer.cpp
+#, fuzzy
+msgid "%s (Already Exists)"
+msgstr "Уже ÑущеÑтвует"
+
+#: editor/editor_asset_installer.cpp
msgid "Uncompressing Assets"
msgstr "РаÑпаковка аÑÑетов"
#: editor/editor_asset_installer.cpp editor/project_manager.cpp
+msgid "The following files failed extraction from package:"
+msgstr "Следующие файлы не удалоÑÑŒ извлечь из пакета:"
+
+#: editor/editor_asset_installer.cpp
+#, fuzzy
+msgid "And %s more files."
+msgstr "Ещё %d файла(ов)"
+
+#: editor/editor_asset_installer.cpp editor/project_manager.cpp
msgid "Package installed successfully!"
msgstr "Пакет уÑпешно уÑтановлен!"
@@ -1260,6 +1275,11 @@ msgstr "Пакет уÑпешно уÑтановлен!"
msgid "Success!"
msgstr "УÑпех!"
+#: editor/editor_asset_installer.cpp
+#, fuzzy
+msgid "Package Contents:"
+msgstr "Содержание:"
+
#: editor/editor_asset_installer.cpp editor/editor_node.cpp
msgid "Install"
msgstr "УÑтановить"
@@ -1398,6 +1418,11 @@ msgid "Invalid file, not an audio bus layout."
msgstr "ÐедопуÑтимый файл, не раÑкладка аудио шины."
#: editor/editor_audio_buses.cpp
+#, fuzzy
+msgid "Error saving file: %s"
+msgstr "Ошибка при Ñохранении файла!"
+
+#: editor/editor_audio_buses.cpp
msgid "Add Bus"
msgstr "Добавить"
@@ -2194,10 +2219,6 @@ msgid "New Window"
msgstr "Ðовое окно"
#: editor/editor_node.cpp
-msgid "Project export failed with error code %d."
-msgstr "ЭкÑпорт проекта не удалÑÑ, код %d."
-
-#: editor/editor_node.cpp
msgid "Imported resources can't be saved."
msgstr "Импортированные реÑурÑÑ‹ не могут быть Ñохранены."
@@ -3112,10 +3133,6 @@ msgstr "Импортировать шаблоны из ZIP файла"
msgid "Template Package"
msgstr "Шаблонный пакет"
-#: editor/editor_node.cpp editor/project_export.cpp
-msgid "Export Project"
-msgstr "ЭкÑпортировать проект"
-
#: editor/editor_node.cpp
msgid "Export Library"
msgstr "ЭкÑпортировать библиотеку"
@@ -3125,10 +3142,6 @@ msgid "Merge With Existing"
msgstr "Объединить Ñ ÑущеÑтвующей"
#: editor/editor_node.cpp
-msgid "Password:"
-msgstr "Пароль:"
-
-#: editor/editor_node.cpp
msgid "Open & Run a Script"
msgstr "Открыть и запуÑтить Ñкрипт"
@@ -3496,8 +3509,9 @@ msgid "Error getting the list of mirrors."
msgstr "Ошибка при Ñоздании объекта подпиÑи."
#: editor/export_template_manager.cpp
+#, fuzzy
msgid "Error parsing JSON of mirror list. Please report this issue!"
-msgstr ""
+msgstr "Ошибка разбора ÑпиÑка зеркал. ПожалуйÑта, Ñообщите об Ñтой проблеме!"
#: editor/export_template_manager.cpp
msgid ""
@@ -5761,6 +5775,23 @@ msgstr "МаÑка излучениÑ"
#: editor/plugins/cpu_particles_2d_editor_plugin.cpp
#: editor/plugins/particles_2d_editor_plugin.cpp
+#, fuzzy
+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
+#, fuzzy
+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 "Из пикÑелÑ"
@@ -5989,8 +6020,9 @@ msgid "Outline Size:"
msgstr "Размер обводки:"
#: editor/plugins/mesh_instance_editor_plugin.cpp
+#, fuzzy
msgid "UV Channel Debug"
-msgstr ""
+msgstr "Отладка УФ канала"
#: editor/plugins/mesh_library_editor_plugin.cpp
msgid "Remove item %d?"
@@ -6643,20 +6675,23 @@ msgstr "Сохранить как..."
#: editor/plugins/script_editor_plugin.cpp
msgid "Can't obtain the script for running."
-msgstr ""
+msgstr "Ðе удаётÑÑ Ð¿Ð¾Ð»ÑƒÑ‡Ð¸Ñ‚ÑŒ Ñкрипт Ð´Ð»Ñ Ð·Ð°Ð¿ÑƒÑка."
#: editor/plugins/script_editor_plugin.cpp
msgid "Script failed reloading, check console for errors."
-msgstr ""
+msgstr "Ðе удалоÑÑŒ перезагрузить Ñкрипт, проверьте конÑоль на наличие ошибок."
#: editor/plugins/script_editor_plugin.cpp
+#, fuzzy
msgid "Script is not in tool mode, will not be able to run."
-msgstr ""
+msgstr "Скрипт не находитÑÑ Ð² режиме инÑтрумента, запуÑк невозможен."
#: editor/plugins/script_editor_plugin.cpp
msgid ""
"To run this script, it must inherit EditorScript and be set to tool mode."
msgstr ""
+"Ð”Ð»Ñ Ð·Ð°Ð¿ÑƒÑка Ñтого Ñкрипта он должен наÑледовать EditorScript и быть "
+"уÑтановлен в режим инÑтрумента."
#: editor/plugins/script_editor_plugin.cpp
msgid "Import Theme"
@@ -7565,8 +7600,9 @@ msgid "Create Polygon2D"
msgstr "Создать Polygon2D"
#: editor/plugins/sprite_editor_plugin.cpp
+#, fuzzy
msgid "Polygon2D Preview"
-msgstr ""
+msgstr "Предварительный проÑмотр Polygon2D"
#: editor/plugins/sprite_editor_plugin.cpp
msgid "Create CollisionPolygon2D"
@@ -8076,8 +8112,9 @@ msgid "Merge from Scene"
msgstr "СлиÑние из Ñцены"
#: editor/plugins/tile_set_editor_plugin.cpp
+#, fuzzy
msgid "New Single Tile"
-msgstr ""
+msgstr "ÐÐ¾Ð²Ð°Ñ Ð¾Ð´Ð¸Ð½Ð¾Ñ‡Ð½Ð°Ñ Ð¿Ð»Ð¸Ñ‚ÐºÐ°"
#: editor/plugins/tile_set_editor_plugin.cpp
#, fuzzy
@@ -9540,6 +9577,10 @@ msgid "Export PCK/Zip"
msgstr "ЭкÑпортировать PCK/Zip"
#: editor/project_export.cpp
+msgid "Export Project"
+msgstr "ЭкÑпортировать проект"
+
+#: editor/project_export.cpp
msgid "Export mode?"
msgstr "Режим ÑкÑпорта?"
@@ -9633,10 +9674,6 @@ msgid "Couldn't create project.godot in project path."
msgstr "Ðе удалоÑÑŒ Ñоздать project.godot в папке проекта."
#: editor/project_manager.cpp
-msgid "The following files failed extraction from package:"
-msgstr "Следующие файлы не удалоÑÑŒ извлечь из пакета:"
-
-#: editor/project_manager.cpp
msgid "Rename Project"
msgstr "Переименовать проект"
@@ -10877,6 +10914,11 @@ msgid "Will load an existing script file."
msgstr "Будет загружен ÑущеÑтвующий Ñкрипт."
#: editor/script_create_dialog.cpp
+#, fuzzy
+msgid "Script file already exists."
+msgstr "Разрез уже ÑущеÑтвует."
+
+#: editor/script_create_dialog.cpp
msgid "Class Name:"
msgstr "Ð˜Ð¼Ñ ÐºÐ»Ð°ÑÑа:"
@@ -12561,7 +12603,15 @@ msgid "This node has been deprecated. Use AnimationTree instead."
msgstr "Этот узел был удален. ВмеÑто Ñтого иÑпользуйте AnimationTree."
#: scene/gui/color_picker.cpp
-msgid "Pick a color from the screen."
+msgid ""
+"Color: #%s\n"
+"LMB: Set color\n"
+"RMB: Remove preset"
+msgstr ""
+
+#: scene/gui/color_picker.cpp
+#, fuzzy
+msgid "Pick a color from the editor window."
msgstr "Выбрать цвет Ñ Ñкрана."
#: scene/gui/color_picker.cpp
@@ -12689,6 +12739,12 @@ msgstr "Ð˜Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ð¼Ð¾Ð³ÑƒÑ‚ быть назначены только Ð
msgid "Constants cannot be modified."
msgstr "КонÑтанты не могут быть изменены."
+#~ msgid "Project export failed with error code %d."
+#~ msgstr "ЭкÑпорт проекта не удалÑÑ, код %d."
+
+#~ msgid "Password:"
+#~ msgstr "Пароль:"
+
#~ msgid "Identifier segments must be of non-zero length."
#~ msgstr "Идентифицированные Ñегменты не должны быть пуÑтыми."
@@ -12985,9 +13041,6 @@ msgstr "КонÑтанты не могут быть изменены."
#~ msgid "Create folder"
#~ msgstr "Создать папку"
-#~ msgid "Already existing"
-#~ msgstr "Уже ÑущеÑтвует"
-
#~ msgid "Custom Node"
#~ msgstr "ПользовательÑкий узел"
@@ -13036,9 +13089,6 @@ msgstr "КонÑтанты не могут быть изменены."
#~ msgid "Split can't form an existing edge."
#~ msgstr "ÐÐµÐ»ÑŒÐ·Ñ Ð¾Ñ‚Ð´ÐµÐ»Ð¸Ñ‚ÑŒ от ÑущеÑтвующего краÑ."
-#~ msgid "Split already exists."
-#~ msgstr "Разрез уже ÑущеÑтвует."
-
#~ msgid "Add Split"
#~ msgstr "Добавить разрез"
diff --git a/editor/translations/si.po b/editor/translations/si.po
index 99e23b323f..3876763252 100644
--- a/editor/translations/si.po
+++ b/editor/translations/si.po
@@ -1177,10 +1177,22 @@ msgid "Error opening package file, not in ZIP format."
msgstr ""
#: editor/editor_asset_installer.cpp
+msgid "%s (Already Exists)"
+msgstr ""
+
+#: editor/editor_asset_installer.cpp
msgid "Uncompressing Assets"
msgstr ""
#: editor/editor_asset_installer.cpp editor/project_manager.cpp
+msgid "The following files failed extraction from package:"
+msgstr ""
+
+#: editor/editor_asset_installer.cpp
+msgid "And %s more files."
+msgstr ""
+
+#: editor/editor_asset_installer.cpp editor/project_manager.cpp
msgid "Package installed successfully!"
msgstr ""
@@ -1189,6 +1201,10 @@ msgstr ""
msgid "Success!"
msgstr ""
+#: editor/editor_asset_installer.cpp
+msgid "Package Contents:"
+msgstr ""
+
#: editor/editor_asset_installer.cpp editor/editor_node.cpp
msgid "Install"
msgstr ""
@@ -1327,6 +1343,10 @@ msgid "Invalid file, not an audio bus layout."
msgstr ""
#: editor/editor_audio_buses.cpp
+msgid "Error saving file: %s"
+msgstr ""
+
+#: editor/editor_audio_buses.cpp
msgid "Add Bus"
msgstr ""
@@ -2100,10 +2120,6 @@ msgid "New Window"
msgstr ""
#: editor/editor_node.cpp
-msgid "Project export failed with error code %d."
-msgstr ""
-
-#: editor/editor_node.cpp
msgid "Imported resources can't be saved."
msgstr ""
@@ -2943,10 +2959,6 @@ msgstr ""
msgid "Template Package"
msgstr ""
-#: editor/editor_node.cpp editor/project_export.cpp
-msgid "Export Project"
-msgstr ""
-
#: editor/editor_node.cpp
msgid "Export Library"
msgstr ""
@@ -2956,10 +2968,6 @@ msgid "Merge With Existing"
msgstr ""
#: editor/editor_node.cpp
-msgid "Password:"
-msgstr ""
-
-#: editor/editor_node.cpp
msgid "Open & Run a Script"
msgstr ""
@@ -5542,6 +5550,21 @@ 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 ""
@@ -9187,6 +9210,10 @@ msgid "Export PCK/Zip"
msgstr ""
#: editor/project_export.cpp
+msgid "Export Project"
+msgstr ""
+
+#: editor/project_export.cpp
msgid "Export mode?"
msgstr ""
@@ -9277,10 +9304,6 @@ msgid "Couldn't create project.godot in project path."
msgstr ""
#: editor/project_manager.cpp
-msgid "The following files failed extraction from package:"
-msgstr ""
-
-#: editor/project_manager.cpp
msgid "Rename Project"
msgstr ""
@@ -10442,6 +10465,10 @@ msgid "Will load an existing script file."
msgstr ""
#: editor/script_create_dialog.cpp
+msgid "Script file already exists."
+msgstr ""
+
+#: editor/script_create_dialog.cpp
msgid "Class Name:"
msgstr ""
@@ -11980,7 +12007,14 @@ msgid "This node has been deprecated. Use AnimationTree instead."
msgstr ""
#: scene/gui/color_picker.cpp
-msgid "Pick a color from the screen."
+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
diff --git a/editor/translations/sk.po b/editor/translations/sk.po
index b7795ea7b7..9760450e61 100644
--- a/editor/translations/sk.po
+++ b/editor/translations/sk.po
@@ -1208,10 +1208,23 @@ msgid "Error opening package file, not in ZIP format."
msgstr "Chyba pri otváraní súboru balíka, nie je vo formáte zip."
#: editor/editor_asset_installer.cpp
+msgid "%s (Already Exists)"
+msgstr ""
+
+#: editor/editor_asset_installer.cpp
msgid "Uncompressing Assets"
msgstr ""
#: editor/editor_asset_installer.cpp editor/project_manager.cpp
+msgid "The following files failed extraction from package:"
+msgstr ""
+
+#: editor/editor_asset_installer.cpp
+#, fuzzy
+msgid "And %s more files."
+msgstr "Vytvoriť adresár"
+
+#: editor/editor_asset_installer.cpp editor/project_manager.cpp
msgid "Package installed successfully!"
msgstr "Balík bol úspešne nainštalovaný!"
@@ -1220,6 +1233,11 @@ msgstr "Balík bol úspešne nainštalovaný!"
msgid "Success!"
msgstr "Úspech!"
+#: editor/editor_asset_installer.cpp
+#, fuzzy
+msgid "Package Contents:"
+msgstr "Konštanty:"
+
#: editor/editor_asset_installer.cpp editor/editor_node.cpp
msgid "Install"
msgstr "Inštalovať"
@@ -1360,6 +1378,11 @@ msgid "Invalid file, not an audio bus layout."
msgstr ""
#: editor/editor_audio_buses.cpp
+#, fuzzy
+msgid "Error saving file: %s"
+msgstr "Chyba pri naÄítaní:"
+
+#: editor/editor_audio_buses.cpp
msgid "Add Bus"
msgstr ""
@@ -2166,10 +2189,6 @@ msgid "New Window"
msgstr ""
#: editor/editor_node.cpp
-msgid "Project export failed with error code %d."
-msgstr ""
-
-#: editor/editor_node.cpp
msgid "Imported resources can't be saved."
msgstr ""
@@ -3022,10 +3041,6 @@ msgstr ""
msgid "Template Package"
msgstr "Všetky vybrané"
-#: editor/editor_node.cpp editor/project_export.cpp
-msgid "Export Project"
-msgstr ""
-
#: editor/editor_node.cpp
msgid "Export Library"
msgstr ""
@@ -3035,10 +3050,6 @@ msgid "Merge With Existing"
msgstr ""
#: editor/editor_node.cpp
-msgid "Password:"
-msgstr ""
-
-#: editor/editor_node.cpp
msgid "Open & Run a Script"
msgstr ""
@@ -5700,6 +5711,22 @@ 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
+#, fuzzy
+msgid "Directed Border Pixels"
+msgstr "PrieÄinky a Súbory:"
+
+#: editor/plugins/cpu_particles_2d_editor_plugin.cpp
+#: editor/plugins/particles_2d_editor_plugin.cpp
msgid "Capture from Pixel"
msgstr ""
@@ -9465,6 +9492,10 @@ msgid "Export PCK/Zip"
msgstr ""
#: editor/project_export.cpp
+msgid "Export Project"
+msgstr ""
+
+#: editor/project_export.cpp
msgid "Export mode?"
msgstr ""
@@ -9557,10 +9588,6 @@ msgid "Couldn't create project.godot in project path."
msgstr ""
#: editor/project_manager.cpp
-msgid "The following files failed extraction from package:"
-msgstr ""
-
-#: editor/project_manager.cpp
#, fuzzy
msgid "Rename Project"
msgstr "Všetky vybrané"
@@ -10753,6 +10780,10 @@ msgid "Will load an existing script file."
msgstr "Popis:"
#: editor/script_create_dialog.cpp
+msgid "Script file already exists."
+msgstr ""
+
+#: editor/script_create_dialog.cpp
#, fuzzy
msgid "Class Name:"
msgstr "Trieda:"
@@ -12347,7 +12378,14 @@ msgid "This node has been deprecated. Use AnimationTree instead."
msgstr ""
#: scene/gui/color_picker.cpp
-msgid "Pick a color from the screen."
+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
diff --git a/editor/translations/sl.po b/editor/translations/sl.po
index 88acbfc946..fd3d3ed35d 100644
--- a/editor/translations/sl.po
+++ b/editor/translations/sl.po
@@ -1251,10 +1251,24 @@ msgid "Error opening package file, not in ZIP format."
msgstr "Napaka pri odpiranju datoteke paketa, ker ni v formatu zip."
#: editor/editor_asset_installer.cpp
+#, fuzzy
+msgid "%s (Already Exists)"
+msgstr "SamodejnoNalaganje '%s' že obstaja!"
+
+#: editor/editor_asset_installer.cpp
msgid "Uncompressing Assets"
msgstr "Razširjenje Dodatkov"
#: editor/editor_asset_installer.cpp editor/project_manager.cpp
+msgid "The following files failed extraction from package:"
+msgstr ""
+
+#: editor/editor_asset_installer.cpp
+#, fuzzy
+msgid "And %s more files."
+msgstr "%d veÄ datotek"
+
+#: editor/editor_asset_installer.cpp editor/project_manager.cpp
#, fuzzy
msgid "Package installed successfully!"
msgstr "Paket je UspeÅ¡no NameÅ¡Äen!"
@@ -1264,6 +1278,11 @@ msgstr "Paket je UspeÅ¡no NameÅ¡Äen!"
msgid "Success!"
msgstr "Uspelo je!"
+#: editor/editor_asset_installer.cpp
+#, fuzzy
+msgid "Package Contents:"
+msgstr "Vsebina:"
+
#: editor/editor_asset_installer.cpp editor/editor_node.cpp
msgid "Install"
msgstr "Namesti"
@@ -1403,6 +1422,11 @@ msgid "Invalid file, not an audio bus layout."
msgstr "Neveljavna datoteka, ker ni postavitve zvoÄnega vodila."
#: editor/editor_audio_buses.cpp
+#, fuzzy
+msgid "Error saving file: %s"
+msgstr "Napaka pri shranjevanju PloÅ¡ÄnegaNiza!"
+
+#: editor/editor_audio_buses.cpp
msgid "Add Bus"
msgstr "Dodaj Vodilo"
@@ -2250,10 +2274,6 @@ msgid "New Window"
msgstr ""
#: editor/editor_node.cpp
-msgid "Project export failed with error code %d."
-msgstr "Izvoz projekta ni uspelo s kodno napako %d."
-
-#: editor/editor_node.cpp
msgid "Imported resources can't be saved."
msgstr ""
@@ -3180,10 +3200,6 @@ msgstr "Uvozi Predloge iz ZIP Datoteke"
msgid "Template Package"
msgstr "Izvozni Upravitelj Predlog"
-#: editor/editor_node.cpp editor/project_export.cpp
-msgid "Export Project"
-msgstr "Izvozi Projekt"
-
#: editor/editor_node.cpp
msgid "Export Library"
msgstr "Izvozi Knjižnico"
@@ -3193,10 +3209,6 @@ msgid "Merge With Existing"
msgstr "Spoji z ObstojeÄim"
#: editor/editor_node.cpp
-msgid "Password:"
-msgstr "Geslo:"
-
-#: editor/editor_node.cpp
msgid "Open & Run a Script"
msgstr "Odpri & Zaženi Skripto"
@@ -5970,6 +5982,22 @@ 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
+#, fuzzy
+msgid "Directed Border Pixels"
+msgstr "Mape & Datoteke:"
+
+#: editor/plugins/cpu_particles_2d_editor_plugin.cpp
+#: editor/plugins/particles_2d_editor_plugin.cpp
msgid "Capture from Pixel"
msgstr ""
@@ -9792,6 +9820,10 @@ msgid "Export PCK/Zip"
msgstr ""
#: editor/project_export.cpp
+msgid "Export Project"
+msgstr "Izvozi Projekt"
+
+#: editor/project_export.cpp
#, fuzzy
msgid "Export mode?"
msgstr "Izvozi Projekt"
@@ -9886,10 +9918,6 @@ msgid "Couldn't create project.godot in project path."
msgstr ""
#: editor/project_manager.cpp
-msgid "The following files failed extraction from package:"
-msgstr ""
-
-#: editor/project_manager.cpp
msgid "Rename Project"
msgstr "Preimenuj Projekt"
@@ -11105,6 +11133,11 @@ msgstr "Naloži obstojeÄo Postavitev Vodila."
#: editor/script_create_dialog.cpp
#, fuzzy
+msgid "Script file already exists."
+msgstr "SamodejnoNalaganje '%s' že obstaja!"
+
+#: editor/script_create_dialog.cpp
+#, fuzzy
msgid "Class Name:"
msgstr "Razred:"
@@ -12722,7 +12755,14 @@ msgid "This node has been deprecated. Use AnimationTree instead."
msgstr ""
#: scene/gui/color_picker.cpp
-msgid "Pick a color from the screen."
+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
@@ -12833,6 +12873,12 @@ msgstr ""
msgid "Constants cannot be modified."
msgstr "Konstante ni možno spreminjati."
+#~ msgid "Project export failed with error code %d."
+#~ msgstr "Izvoz projekta ni uspelo s kodno napako %d."
+
+#~ msgid "Password:"
+#~ msgstr "Geslo:"
+
#~ msgid "Pause the scene"
#~ msgstr "Zaustavi prizor"
@@ -13012,10 +13058,6 @@ msgstr "Konstante ni možno spreminjati."
#~ msgstr "Stolpec:"
#, fuzzy
-#~ msgid "Split already exists."
-#~ msgstr "SamodejnoNalaganje '%s' že obstaja!"
-
-#, fuzzy
#~ msgid "Add Split"
#~ msgstr "Dodaj toÄko"
diff --git a/editor/translations/sq.po b/editor/translations/sq.po
index fc175ff061..398a9072b8 100644
--- a/editor/translations/sq.po
+++ b/editor/translations/sq.po
@@ -1190,10 +1190,24 @@ msgid "Error opening package file, not in ZIP format."
msgstr "Gabim në hapjen e skedarit paketë, nuk është në formatin zip."
#: editor/editor_asset_installer.cpp
+#, fuzzy
+msgid "%s (Already Exists)"
+msgstr "Autoload '%s' egziston!"
+
+#: editor/editor_asset_installer.cpp
msgid "Uncompressing Assets"
msgstr "Duke Dekompresuar Asetet"
#: editor/editor_asset_installer.cpp editor/project_manager.cpp
+msgid "The following files failed extraction from package:"
+msgstr ""
+
+#: editor/editor_asset_installer.cpp
+#, fuzzy
+msgid "And %s more files."
+msgstr "%d skedarë më shumë"
+
+#: editor/editor_asset_installer.cpp editor/project_manager.cpp
msgid "Package installed successfully!"
msgstr "Paketa u instalua me sukses!"
@@ -1202,6 +1216,11 @@ msgstr "Paketa u instalua me sukses!"
msgid "Success!"
msgstr "Sukses!"
+#: editor/editor_asset_installer.cpp
+#, fuzzy
+msgid "Package Contents:"
+msgstr "Instaluesi Paketave"
+
#: editor/editor_asset_installer.cpp editor/editor_node.cpp
msgid "Install"
msgstr "Instalo"
@@ -1340,6 +1359,11 @@ msgid "Invalid file, not an audio bus layout."
msgstr ""
#: editor/editor_audio_buses.cpp
+#, fuzzy
+msgid "Error saving file: %s"
+msgstr "Gabim gjatë ruajtjes së TileSet-it!"
+
+#: editor/editor_audio_buses.cpp
msgid "Add Bus"
msgstr ""
@@ -2170,10 +2194,6 @@ msgid "New Window"
msgstr ""
#: editor/editor_node.cpp
-msgid "Project export failed with error code %d."
-msgstr "Eksportimi i projektit dështoi me kodin e gabimit %d."
-
-#: editor/editor_node.cpp
msgid "Imported resources can't be saved."
msgstr "Resurset e importuara nuk mund të ruhen."
@@ -3102,10 +3122,6 @@ msgstr "Importo Shabllonet Nga Skedari ZIP"
msgid "Template Package"
msgstr "Menaxheri i Shablloneve të Eksportimit"
-#: editor/editor_node.cpp editor/project_export.cpp
-msgid "Export Project"
-msgstr "Eksporto Projektin"
-
#: editor/editor_node.cpp
msgid "Export Library"
msgstr "Libraria e Eksportit"
@@ -3115,10 +3131,6 @@ msgid "Merge With Existing"
msgstr "Bashko Me Ekzistuesin"
#: editor/editor_node.cpp
-msgid "Password:"
-msgstr "Fjalëkalimi:"
-
-#: editor/editor_node.cpp
msgid "Open & Run a Script"
msgstr "Hap & Fillo një Shkrim"
@@ -5761,6 +5773,22 @@ 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
+#, fuzzy
+msgid "Directed Border Pixels"
+msgstr "Direktorit & Skedarët:"
+
+#: editor/plugins/cpu_particles_2d_editor_plugin.cpp
+#: editor/plugins/particles_2d_editor_plugin.cpp
msgid "Capture from Pixel"
msgstr ""
@@ -9445,6 +9473,10 @@ msgid "Export PCK/Zip"
msgstr ""
#: editor/project_export.cpp
+msgid "Export Project"
+msgstr "Eksporto Projektin"
+
+#: editor/project_export.cpp
msgid "Export mode?"
msgstr ""
@@ -9536,10 +9568,6 @@ msgid "Couldn't create project.godot in project path."
msgstr ""
#: editor/project_manager.cpp
-msgid "The following files failed extraction from package:"
-msgstr ""
-
-#: editor/project_manager.cpp
msgid "Rename Project"
msgstr ""
@@ -10725,6 +10753,11 @@ msgstr ""
#: editor/script_create_dialog.cpp
#, fuzzy
+msgid "Script file already exists."
+msgstr "Emri i grupit ekziston që më parë."
+
+#: editor/script_create_dialog.cpp
+#, fuzzy
msgid "Class Name:"
msgstr "Klasa:"
@@ -12282,7 +12315,14 @@ msgid "This node has been deprecated. Use AnimationTree instead."
msgstr ""
#: scene/gui/color_picker.cpp
-msgid "Pick a color from the screen."
+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
@@ -12386,6 +12426,12 @@ msgstr ""
msgid "Constants cannot be modified."
msgstr ""
+#~ msgid "Project export failed with error code %d."
+#~ msgstr "Eksportimi i projektit dështoi me kodin e gabimit %d."
+
+#~ msgid "Password:"
+#~ msgstr "Fjalëkalimi:"
+
#~ msgid "Pause the scene"
#~ msgstr "Pusho skenën"
diff --git a/editor/translations/sr_Cyrl.po b/editor/translations/sr_Cyrl.po
index 9b940d334c..3d0341383f 100644
--- a/editor/translations/sr_Cyrl.po
+++ b/editor/translations/sr_Cyrl.po
@@ -1253,10 +1253,24 @@ msgid "Error opening package file, not in ZIP format."
msgstr "Грешка при отварању датотеку пакета. Датотека није zip формата."
#: editor/editor_asset_installer.cpp
+#, fuzzy
+msgid "%s (Already Exists)"
+msgstr "ÐутоматÑко учитавање '%s' већ поÑтоји!"
+
+#: editor/editor_asset_installer.cpp
msgid "Uncompressing Assets"
msgstr "ДекомпреÑија ÑредÑтва"
#: editor/editor_asset_installer.cpp editor/project_manager.cpp
+msgid "The following files failed extraction from package:"
+msgstr ""
+
+#: editor/editor_asset_installer.cpp
+#, fuzzy
+msgid "And %s more files."
+msgstr "још %d датотека/е"
+
+#: editor/editor_asset_installer.cpp editor/project_manager.cpp
#, fuzzy
msgid "Package installed successfully!"
msgstr "Пакет је инÑталиран уÑпешно!"
@@ -1266,6 +1280,11 @@ msgstr "Пакет је инÑталиран уÑпешно!"
msgid "Success!"
msgstr "УÑпех!"
+#: editor/editor_asset_installer.cpp
+#, fuzzy
+msgid "Package Contents:"
+msgstr "Садржај:"
+
#: editor/editor_asset_installer.cpp editor/editor_node.cpp
msgid "Install"
msgstr "ИнÑталирај"
@@ -1406,6 +1425,11 @@ msgid "Invalid file, not an audio bus layout."
msgstr "Датотека не Ñадржи раÑпоред звучног баÑа."
#: editor/editor_audio_buses.cpp
+#, fuzzy
+msgid "Error saving file: %s"
+msgstr "Грешка при чувању TileSet!"
+
+#: editor/editor_audio_buses.cpp
msgid "Add Bus"
msgstr "Додај баÑ"
@@ -2255,10 +2279,6 @@ msgid "New Window"
msgstr ""
#: editor/editor_node.cpp
-msgid "Project export failed with error code %d."
-msgstr ""
-
-#: editor/editor_node.cpp
msgid "Imported resources can't be saved."
msgstr ""
@@ -3188,10 +3208,6 @@ msgstr "Увези шаблоне из ZIP датотеке"
msgid "Template Package"
msgstr "Менаџер извозних шаблона"
-#: editor/editor_node.cpp editor/project_export.cpp
-msgid "Export Project"
-msgstr "Извези пројекат"
-
#: editor/editor_node.cpp
msgid "Export Library"
msgstr "Извези библиотеку"
@@ -3201,10 +3217,6 @@ msgid "Merge With Existing"
msgstr "Споји Ñа поÑтојећим"
#: editor/editor_node.cpp
-msgid "Password:"
-msgstr "Лозинка:"
-
-#: editor/editor_node.cpp
msgid "Open & Run a Script"
msgstr "Отвори и покрени Ñкриптицу"
@@ -5997,6 +6009,22 @@ 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
+#, fuzzy
+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 "Сними од пикÑела"
@@ -9912,6 +9940,10 @@ msgid "Export PCK/Zip"
msgstr "Извоз PCK/Zip"
#: editor/project_export.cpp
+msgid "Export Project"
+msgstr "Извези пројекат"
+
+#: editor/project_export.cpp
#, fuzzy
msgid "Export mode?"
msgstr "Режим извоза:"
@@ -10007,10 +10039,6 @@ msgid "Couldn't create project.godot in project path."
msgstr ""
#: editor/project_manager.cpp
-msgid "The following files failed extraction from package:"
-msgstr ""
-
-#: editor/project_manager.cpp
msgid "Rename Project"
msgstr ""
@@ -11233,6 +11261,11 @@ msgstr "Учитај поÑтојећи Ð±Ð°Ñ Ñ€Ð°Ñпоред."
#: editor/script_create_dialog.cpp
#, fuzzy
+msgid "Script file already exists."
+msgstr "ÐутоматÑко учитавање '%s' већ поÑтоји!"
+
+#: editor/script_create_dialog.cpp
+#, fuzzy
msgid "Class Name:"
msgstr "КлаÑа:"
@@ -12832,7 +12865,14 @@ msgid "This node has been deprecated. Use AnimationTree instead."
msgstr ""
#: scene/gui/color_picker.cpp
-msgid "Pick a color from the screen."
+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
@@ -12939,6 +12979,9 @@ msgstr ""
msgid "Constants cannot be modified."
msgstr ""
+#~ msgid "Password:"
+#~ msgstr "Лозинка:"
+
#~ msgid "Pause the scene"
#~ msgstr "Паузирај Ñцену"
@@ -13174,10 +13217,6 @@ msgstr ""
#~ msgstr "Колона:"
#, fuzzy
-#~ msgid "Split already exists."
-#~ msgstr "ÐутоматÑко учитавање '%s' већ поÑтоји!"
-
-#, fuzzy
#~ msgid "Add Split"
#~ msgstr "Додај тачку"
diff --git a/editor/translations/sr_Latn.po b/editor/translations/sr_Latn.po
index 9710a5f670..b9aa895863 100644
--- a/editor/translations/sr_Latn.po
+++ b/editor/translations/sr_Latn.po
@@ -1186,10 +1186,22 @@ msgid "Error opening package file, not in ZIP format."
msgstr ""
#: editor/editor_asset_installer.cpp
+msgid "%s (Already Exists)"
+msgstr ""
+
+#: editor/editor_asset_installer.cpp
msgid "Uncompressing Assets"
msgstr ""
#: editor/editor_asset_installer.cpp editor/project_manager.cpp
+msgid "The following files failed extraction from package:"
+msgstr ""
+
+#: editor/editor_asset_installer.cpp
+msgid "And %s more files."
+msgstr ""
+
+#: editor/editor_asset_installer.cpp editor/project_manager.cpp
msgid "Package installed successfully!"
msgstr ""
@@ -1198,6 +1210,10 @@ msgstr ""
msgid "Success!"
msgstr ""
+#: editor/editor_asset_installer.cpp
+msgid "Package Contents:"
+msgstr ""
+
#: editor/editor_asset_installer.cpp editor/editor_node.cpp
msgid "Install"
msgstr ""
@@ -1336,6 +1352,10 @@ msgid "Invalid file, not an audio bus layout."
msgstr ""
#: editor/editor_audio_buses.cpp
+msgid "Error saving file: %s"
+msgstr ""
+
+#: editor/editor_audio_buses.cpp
msgid "Add Bus"
msgstr ""
@@ -2113,10 +2133,6 @@ msgid "New Window"
msgstr ""
#: editor/editor_node.cpp
-msgid "Project export failed with error code %d."
-msgstr ""
-
-#: editor/editor_node.cpp
msgid "Imported resources can't be saved."
msgstr ""
@@ -2958,10 +2974,6 @@ msgstr ""
msgid "Template Package"
msgstr ""
-#: editor/editor_node.cpp editor/project_export.cpp
-msgid "Export Project"
-msgstr ""
-
#: editor/editor_node.cpp
msgid "Export Library"
msgstr ""
@@ -2971,10 +2983,6 @@ msgid "Merge With Existing"
msgstr ""
#: editor/editor_node.cpp
-msgid "Password:"
-msgstr ""
-
-#: editor/editor_node.cpp
msgid "Open & Run a Script"
msgstr ""
@@ -5570,6 +5578,21 @@ 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 ""
@@ -9260,6 +9283,10 @@ msgid "Export PCK/Zip"
msgstr ""
#: editor/project_export.cpp
+msgid "Export Project"
+msgstr ""
+
+#: editor/project_export.cpp
msgid "Export mode?"
msgstr ""
@@ -9350,10 +9377,6 @@ msgid "Couldn't create project.godot in project path."
msgstr ""
#: editor/project_manager.cpp
-msgid "The following files failed extraction from package:"
-msgstr ""
-
-#: editor/project_manager.cpp
msgid "Rename Project"
msgstr ""
@@ -10522,6 +10545,10 @@ msgid "Will load an existing script file."
msgstr ""
#: editor/script_create_dialog.cpp
+msgid "Script file already exists."
+msgstr ""
+
+#: editor/script_create_dialog.cpp
msgid "Class Name:"
msgstr ""
@@ -12066,7 +12093,14 @@ msgid "This node has been deprecated. Use AnimationTree instead."
msgstr ""
#: scene/gui/color_picker.cpp
-msgid "Pick a color from the screen."
+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
diff --git a/editor/translations/sv.po b/editor/translations/sv.po
index b0727bc604..0a949e6f4e 100644
--- a/editor/translations/sv.po
+++ b/editor/translations/sv.po
@@ -1240,10 +1240,24 @@ msgid "Error opening package file, not in ZIP format."
msgstr "Fel vid öppning av paketetfil, inte i zip-format."
#: editor/editor_asset_installer.cpp
+#, fuzzy
+msgid "%s (Already Exists)"
+msgstr "Autoload '%s' finns redan!"
+
+#: editor/editor_asset_installer.cpp
msgid "Uncompressing Assets"
msgstr "Dekomprimerar Tillgångar"
#: editor/editor_asset_installer.cpp editor/project_manager.cpp
+msgid "The following files failed extraction from package:"
+msgstr ""
+
+#: editor/editor_asset_installer.cpp
+#, fuzzy
+msgid "And %s more files."
+msgstr "%d fler filer"
+
+#: editor/editor_asset_installer.cpp editor/project_manager.cpp
#, fuzzy
msgid "Package installed successfully!"
msgstr "Paketet installerades!"
@@ -1253,6 +1267,11 @@ msgstr "Paketet installerades!"
msgid "Success!"
msgstr "Klart!"
+#: editor/editor_asset_installer.cpp
+#, fuzzy
+msgid "Package Contents:"
+msgstr "Innehåll:"
+
#: editor/editor_asset_installer.cpp editor/editor_node.cpp
msgid "Install"
msgstr "Installera"
@@ -1395,6 +1414,11 @@ msgid "Invalid file, not an audio bus layout."
msgstr "Ogiltig fil, inte en Ljud-Buss Layout."
#: editor/editor_audio_buses.cpp
+#, fuzzy
+msgid "Error saving file: %s"
+msgstr "Fel vid sparande av TileSet!"
+
+#: editor/editor_audio_buses.cpp
msgid "Add Bus"
msgstr "Lägg till Buss"
@@ -2240,10 +2264,6 @@ msgid "New Window"
msgstr ""
#: editor/editor_node.cpp
-msgid "Project export failed with error code %d."
-msgstr "Projekt exporten misslyckades med följande felmeddelande %d."
-
-#: editor/editor_node.cpp
msgid "Imported resources can't be saved."
msgstr ""
@@ -3156,10 +3176,6 @@ msgstr "Importera Mall från ZIP fil"
msgid "Template Package"
msgstr "Mallar"
-#: editor/editor_node.cpp editor/project_export.cpp
-msgid "Export Project"
-msgstr "Exportera Projekt"
-
#: editor/editor_node.cpp
msgid "Export Library"
msgstr "Exportera Bibliotek"
@@ -3169,10 +3185,6 @@ msgid "Merge With Existing"
msgstr "Sammanfoga Med Existerande"
#: editor/editor_node.cpp
-msgid "Password:"
-msgstr "Lösenord:"
-
-#: editor/editor_node.cpp
msgid "Open & Run a Script"
msgstr "Öppna & Kör ett Skript"
@@ -5917,6 +5929,22 @@ 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
+#, fuzzy
+msgid "Directed Border Pixels"
+msgstr "Kataloger & Filer:"
+
+#: editor/plugins/cpu_particles_2d_editor_plugin.cpp
+#: editor/plugins/particles_2d_editor_plugin.cpp
msgid "Capture from Pixel"
msgstr ""
@@ -9732,6 +9760,10 @@ msgid "Export PCK/Zip"
msgstr "Exportera PCK/Zip"
#: editor/project_export.cpp
+msgid "Export Project"
+msgstr "Exportera Projekt"
+
+#: editor/project_export.cpp
#, fuzzy
msgid "Export mode?"
msgstr "Exportera Projekt"
@@ -9827,10 +9859,6 @@ msgid "Couldn't create project.godot in project path."
msgstr ""
#: editor/project_manager.cpp
-msgid "The following files failed extraction from package:"
-msgstr ""
-
-#: editor/project_manager.cpp
msgid "Rename Project"
msgstr "Byt namn på Projekt"
@@ -11057,6 +11085,11 @@ msgstr "Ladda in befintlig Skript-fil"
#: editor/script_create_dialog.cpp
#, fuzzy
+msgid "Script file already exists."
+msgstr "Autoload '%s' finns redan!"
+
+#: editor/script_create_dialog.cpp
+#, fuzzy
msgid "Class Name:"
msgstr "Klassnamn"
@@ -12672,7 +12705,14 @@ msgid "This node has been deprecated. Use AnimationTree instead."
msgstr ""
#: scene/gui/color_picker.cpp
-msgid "Pick a color from the screen."
+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
@@ -12780,6 +12820,12 @@ msgstr ""
msgid "Constants cannot be modified."
msgstr ""
+#~ msgid "Project export failed with error code %d."
+#~ msgstr "Projekt exporten misslyckades med följande felmeddelande %d."
+
+#~ msgid "Password:"
+#~ msgstr "Lösenord:"
+
#~ msgid "Pause the scene"
#~ msgstr "Pausa scenen"
@@ -12974,10 +13020,6 @@ msgstr ""
#~ "Node."
#, fuzzy
-#~ msgid "Split already exists."
-#~ msgstr "Autoload '%s' finns redan!"
-
-#, fuzzy
#~ msgid "Remove Split"
#~ msgstr "Ta Bort Mall"
diff --git a/editor/translations/ta.po b/editor/translations/ta.po
index 570f4ff728..7e85c8a469 100644
--- a/editor/translations/ta.po
+++ b/editor/translations/ta.po
@@ -1178,10 +1178,22 @@ msgid "Error opening package file, not in ZIP format."
msgstr ""
#: editor/editor_asset_installer.cpp
+msgid "%s (Already Exists)"
+msgstr ""
+
+#: editor/editor_asset_installer.cpp
msgid "Uncompressing Assets"
msgstr ""
#: editor/editor_asset_installer.cpp editor/project_manager.cpp
+msgid "The following files failed extraction from package:"
+msgstr ""
+
+#: editor/editor_asset_installer.cpp
+msgid "And %s more files."
+msgstr ""
+
+#: editor/editor_asset_installer.cpp editor/project_manager.cpp
msgid "Package installed successfully!"
msgstr ""
@@ -1190,6 +1202,10 @@ msgstr ""
msgid "Success!"
msgstr ""
+#: editor/editor_asset_installer.cpp
+msgid "Package Contents:"
+msgstr ""
+
#: editor/editor_asset_installer.cpp editor/editor_node.cpp
msgid "Install"
msgstr ""
@@ -1328,6 +1344,10 @@ msgid "Invalid file, not an audio bus layout."
msgstr ""
#: editor/editor_audio_buses.cpp
+msgid "Error saving file: %s"
+msgstr ""
+
+#: editor/editor_audio_buses.cpp
msgid "Add Bus"
msgstr ""
@@ -2102,10 +2122,6 @@ msgid "New Window"
msgstr ""
#: editor/editor_node.cpp
-msgid "Project export failed with error code %d."
-msgstr ""
-
-#: editor/editor_node.cpp
msgid "Imported resources can't be saved."
msgstr ""
@@ -2946,10 +2962,6 @@ msgstr ""
msgid "Template Package"
msgstr ""
-#: editor/editor_node.cpp editor/project_export.cpp
-msgid "Export Project"
-msgstr ""
-
#: editor/editor_node.cpp
msgid "Export Library"
msgstr ""
@@ -2959,10 +2971,6 @@ msgid "Merge With Existing"
msgstr ""
#: editor/editor_node.cpp
-msgid "Password:"
-msgstr ""
-
-#: editor/editor_node.cpp
msgid "Open & Run a Script"
msgstr ""
@@ -5544,6 +5552,21 @@ 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 ""
@@ -9183,6 +9206,10 @@ msgid "Export PCK/Zip"
msgstr ""
#: editor/project_export.cpp
+msgid "Export Project"
+msgstr ""
+
+#: editor/project_export.cpp
msgid "Export mode?"
msgstr ""
@@ -9273,10 +9300,6 @@ msgid "Couldn't create project.godot in project path."
msgstr ""
#: editor/project_manager.cpp
-msgid "The following files failed extraction from package:"
-msgstr ""
-
-#: editor/project_manager.cpp
msgid "Rename Project"
msgstr ""
@@ -10441,6 +10464,10 @@ msgid "Will load an existing script file."
msgstr ""
#: editor/script_create_dialog.cpp
+msgid "Script file already exists."
+msgstr ""
+
+#: editor/script_create_dialog.cpp
msgid "Class Name:"
msgstr ""
@@ -11976,7 +12003,14 @@ msgid "This node has been deprecated. Use AnimationTree instead."
msgstr ""
#: scene/gui/color_picker.cpp
-msgid "Pick a color from the screen."
+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
diff --git a/editor/translations/te.po b/editor/translations/te.po
index e7f6f52938..3943a5f713 100644
--- a/editor/translations/te.po
+++ b/editor/translations/te.po
@@ -1156,10 +1156,22 @@ msgid "Error opening package file, not in ZIP format."
msgstr ""
#: editor/editor_asset_installer.cpp
+msgid "%s (Already Exists)"
+msgstr ""
+
+#: editor/editor_asset_installer.cpp
msgid "Uncompressing Assets"
msgstr ""
#: editor/editor_asset_installer.cpp editor/project_manager.cpp
+msgid "The following files failed extraction from package:"
+msgstr ""
+
+#: editor/editor_asset_installer.cpp
+msgid "And %s more files."
+msgstr ""
+
+#: editor/editor_asset_installer.cpp editor/project_manager.cpp
msgid "Package installed successfully!"
msgstr ""
@@ -1168,6 +1180,10 @@ msgstr ""
msgid "Success!"
msgstr ""
+#: editor/editor_asset_installer.cpp
+msgid "Package Contents:"
+msgstr ""
+
#: editor/editor_asset_installer.cpp editor/editor_node.cpp
msgid "Install"
msgstr ""
@@ -1306,6 +1322,10 @@ msgid "Invalid file, not an audio bus layout."
msgstr ""
#: editor/editor_audio_buses.cpp
+msgid "Error saving file: %s"
+msgstr ""
+
+#: editor/editor_audio_buses.cpp
msgid "Add Bus"
msgstr ""
@@ -2078,10 +2098,6 @@ msgid "New Window"
msgstr ""
#: editor/editor_node.cpp
-msgid "Project export failed with error code %d."
-msgstr ""
-
-#: editor/editor_node.cpp
msgid "Imported resources can't be saved."
msgstr ""
@@ -2920,10 +2936,6 @@ msgstr ""
msgid "Template Package"
msgstr ""
-#: editor/editor_node.cpp editor/project_export.cpp
-msgid "Export Project"
-msgstr ""
-
#: editor/editor_node.cpp
msgid "Export Library"
msgstr ""
@@ -2933,10 +2945,6 @@ msgid "Merge With Existing"
msgstr ""
#: editor/editor_node.cpp
-msgid "Password:"
-msgstr ""
-
-#: editor/editor_node.cpp
msgid "Open & Run a Script"
msgstr ""
@@ -5498,6 +5506,21 @@ 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 ""
@@ -9115,6 +9138,10 @@ msgid "Export PCK/Zip"
msgstr ""
#: editor/project_export.cpp
+msgid "Export Project"
+msgstr ""
+
+#: editor/project_export.cpp
msgid "Export mode?"
msgstr ""
@@ -9205,10 +9232,6 @@ msgid "Couldn't create project.godot in project path."
msgstr ""
#: editor/project_manager.cpp
-msgid "The following files failed extraction from package:"
-msgstr ""
-
-#: editor/project_manager.cpp
msgid "Rename Project"
msgstr ""
@@ -10367,6 +10390,10 @@ msgid "Will load an existing script file."
msgstr ""
#: editor/script_create_dialog.cpp
+msgid "Script file already exists."
+msgstr ""
+
+#: editor/script_create_dialog.cpp
msgid "Class Name:"
msgstr ""
@@ -11892,7 +11919,14 @@ msgid "This node has been deprecated. Use AnimationTree instead."
msgstr ""
#: scene/gui/color_picker.cpp
-msgid "Pick a color from the screen."
+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
diff --git a/editor/translations/th.po b/editor/translations/th.po
index 6de9e03612..f027ef1ccb 100644
--- a/editor/translations/th.po
+++ b/editor/translations/th.po
@@ -2,16 +2,15 @@
# Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur.
# Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md).
# This file is distributed under the same license as the Godot source code.
-#
# Kaveeta Vivatchai <goodytong@gmail.com>, 2017.
# Poommetee Ketson (Noshyaar) <poommetee@protonmail.com>, 2017-2018.
-#
+# Thanachart Monpassorn <nunf_2539@hotmail.com>, 2020.
msgid ""
msgstr ""
"Project-Id-Version: Godot Engine editor\n"
"POT-Creation-Date: \n"
-"PO-Revision-Date: 2018-12-13 14:43+0100\n"
-"Last-Translator: Poommetee Ketson <poommetee@protonmail.com>\n"
+"PO-Revision-Date: 2020-01-03 21:21+0000\n"
+"Last-Translator: Thanachart Monpassorn <nunf_2539@hotmail.com>\n"
"Language-Team: Thai <https://hosted.weblate.org/projects/godot-engine/godot/"
"th/>\n"
"Language: th\n"
@@ -19,7 +18,7 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=1; plural=0;\n"
-"X-Generator: Poedit 2.2\n"
+"X-Generator: Weblate 3.10\n"
#: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp
#: modules/visual_script/visual_script_builtin_funcs.cpp
@@ -28,7 +27,7 @@ msgstr "ตัวà¹à¸›à¸£à¹ƒà¸™ convert() ผิดพลาด ใช้ค่
#: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp
msgid "Expected a string of length 1 (a character)."
-msgstr ""
+msgstr "พบ String ที่มีความยาวเท่าà¸à¸±à¸š 1 (ตัวอัà¸à¸©à¸£)"
#: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp
#: modules/mono/glue/gd_glue.cpp
@@ -38,11 +37,11 @@ msgstr "ไบต์ไม่ครบหรือผิดรูปà¹à¸šà¸š à¹
#: core/math/expression.cpp
msgid "Invalid input %i (not passed) in expression"
-msgstr ""
+msgstr "ค่าอินพุตผิดพลาด %i (ไม่ผ่าน)"
#: core/math/expression.cpp
msgid "self can't be used because instance is null (not passed)"
-msgstr ""
+msgstr "self ไม่สามารถใช้ได้เนื่องจาภinstance มีค่า null (ไม่ผ่าน)"
#: core/math/expression.cpp
#, fuzzy
@@ -69,40 +68,39 @@ msgstr ""
#: core/ustring.cpp
msgid "B"
-msgstr ""
+msgstr "B"
#: core/ustring.cpp
msgid "KiB"
-msgstr ""
+msgstr "KiB"
#: core/ustring.cpp
-#, fuzzy
msgid "MiB"
-msgstr "ร่วม"
+msgstr "MiB"
#: core/ustring.cpp
msgid "GiB"
-msgstr ""
+msgstr "GiB"
#: core/ustring.cpp
msgid "TiB"
-msgstr ""
+msgstr "TiB"
#: core/ustring.cpp
msgid "PiB"
-msgstr ""
+msgstr "PiB"
#: core/ustring.cpp
msgid "EiB"
-msgstr ""
+msgstr "EiB"
#: editor/animation_bezier_editor.cpp
msgid "Free"
-msgstr "ฟรี"
+msgstr "อิสระ"
#: editor/animation_bezier_editor.cpp
msgid "Balanced"
-msgstr ""
+msgstr "สมดุล"
#: editor/animation_bezier_editor.cpp
#, fuzzy
@@ -114,9 +112,8 @@ msgid "Time:"
msgstr "เวลา:"
#: editor/animation_bezier_editor.cpp
-#, fuzzy
msgid "Value:"
-msgstr "ค่า"
+msgstr "ค่า:"
#: editor/animation_bezier_editor.cpp
#, fuzzy
@@ -1252,10 +1249,24 @@ msgid "Error opening package file, not in ZIP format."
msgstr "ผิดพลาดขณะเปิดไฟล์à¹à¸žà¸„เà¸à¸ˆ, ไม่ใช่รูปà¹à¸šà¸š zip"
#: editor/editor_asset_installer.cpp
+#, fuzzy
+msgid "%s (Already Exists)"
+msgstr "มีอยู่à¸à¹ˆà¸­à¸™à¹à¸¥à¹‰à¸§"
+
+#: editor/editor_asset_installer.cpp
msgid "Uncompressing Assets"
msgstr "à¸à¸³à¸¥à¸±à¸‡à¸„ลายบีบอัด"
#: editor/editor_asset_installer.cpp editor/project_manager.cpp
+msgid "The following files failed extraction from package:"
+msgstr "ผิดพลาดขณะà¹à¸¢à¸à¹„ฟล์ต่อไปนี้จาà¸à¹à¸žà¸„เà¸à¸ˆ:"
+
+#: editor/editor_asset_installer.cpp
+#, fuzzy
+msgid "And %s more files."
+msgstr "à¹à¸¥à¸°à¸­à¸µà¸ %d ไฟล์"
+
+#: editor/editor_asset_installer.cpp editor/project_manager.cpp
#, fuzzy
msgid "Package installed successfully!"
msgstr "ติดตั้งà¹à¸žà¸„เà¸à¸ˆà¹€à¸ªà¸£à¹‡à¸ˆà¸ªà¸¡à¸šà¸¹à¸£à¸“์!"
@@ -1265,6 +1276,11 @@ msgstr "ติดตั้งà¹à¸žà¸„เà¸à¸ˆà¹€à¸ªà¸£à¹‡à¸ˆà¸ªà¸¡à¸šà¸¹à¸£à¸“
msgid "Success!"
msgstr "สำเร็จ!"
+#: editor/editor_asset_installer.cpp
+#, fuzzy
+msgid "Package Contents:"
+msgstr "ประà¸à¸­à¸šà¸”้วย:"
+
#: editor/editor_asset_installer.cpp editor/editor_node.cpp
msgid "Install"
msgstr "ติดตั้ง"
@@ -1404,6 +1420,11 @@ msgid "Invalid file, not an audio bus layout."
msgstr "ไฟล์ไม่ถูà¸à¸•à¹‰à¸­à¸‡ ไม่ใช่เลย์เอาต์ของ Audio Bus"
#: editor/editor_audio_buses.cpp
+#, fuzzy
+msgid "Error saving file: %s"
+msgstr "ผิดพลาดขณะบันทึภTileSet!"
+
+#: editor/editor_audio_buses.cpp
msgid "Add Bus"
msgstr "เพิ่ม Bus"
@@ -2250,10 +2271,6 @@ msgid "New Window"
msgstr "หน้าต่าง"
#: editor/editor_node.cpp
-msgid "Project export failed with error code %d."
-msgstr ""
-
-#: editor/editor_node.cpp
msgid "Imported resources can't be saved."
msgstr ""
@@ -3154,10 +3171,6 @@ msgstr "นำเข้าà¹à¸¡à¹ˆà¹à¸šà¸šà¸ˆà¸²à¸à¹„ฟล์ ZIP"
msgid "Template Package"
msgstr "จัดà¸à¸²à¸£à¹à¸¡à¹ˆà¹à¸šà¸šà¸ªà¹ˆà¸‡à¸­à¸­à¸"
-#: editor/editor_node.cpp editor/project_export.cpp
-msgid "Export Project"
-msgstr "ส่งออà¸à¹‚ปรเจà¸à¸•à¹Œ"
-
#: editor/editor_node.cpp
msgid "Export Library"
msgstr "ส่งออà¸à¹„ลบรารี"
@@ -3167,10 +3180,6 @@ msgid "Merge With Existing"
msgstr "รวมà¸à¸±à¸šà¸—ี่มีอยู่เดิม"
#: editor/editor_node.cpp
-msgid "Password:"
-msgstr "รหัสผ่าน:"
-
-#: editor/editor_node.cpp
msgid "Open & Run a Script"
msgstr "เปิดà¹à¸¥à¸°à¸£à¸±à¸™à¸ªà¸„ริปต์"
@@ -3808,26 +3817,22 @@ msgid "New Scene..."
msgstr "ฉาà¸à¹ƒà¸«à¸¡à¹ˆ"
#: editor/filesystem_dock.cpp editor/plugins/script_editor_plugin.cpp
-#, fuzzy
msgid "New Script..."
-msgstr "สคริปต์ใหม่"
+msgstr "สคริปต์ใหม่..."
#: editor/filesystem_dock.cpp
-#, fuzzy
msgid "New Resource..."
-msgstr "บันทึà¸à¸£à¸µà¸‹à¸­à¸£à¹Œà¸ªà¹€à¸›à¹‡à¸™..."
+msgstr "ทรัพยาà¸à¸£à¹ƒà¸«à¸¡à¹ˆ"
#: editor/filesystem_dock.cpp editor/plugins/visual_shader_editor_plugin.cpp
#: editor/script_editor_debugger.cpp
-#, fuzzy
msgid "Expand All"
-msgstr "ขยายโฟลเดอร์"
+msgstr "ขยายออà¸"
#: editor/filesystem_dock.cpp editor/plugins/visual_shader_editor_plugin.cpp
#: editor/script_editor_debugger.cpp
-#, fuzzy
msgid "Collapse All"
-msgstr "ยุบโฟลเดอร์"
+msgstr "ยุบเข้า"
#: editor/filesystem_dock.cpp
#: editor/plugins/animation_tree_player_editor_plugin.cpp
@@ -3837,14 +3842,12 @@ msgid "Rename"
msgstr "เปลี่ยนชื่อ"
#: editor/filesystem_dock.cpp
-#, fuzzy
msgid "Previous Folder/File"
-msgstr "ไปชั้นล่าง"
+msgstr "ไฟล์/โฟลเดอร์à¸à¹ˆà¸­à¸™à¸«à¸™à¹‰à¸²"
#: editor/filesystem_dock.cpp
-#, fuzzy
msgid "Next Folder/File"
-msgstr "ไปชั้นบน"
+msgstr "โฟลเดอร์/ไฟล์ ถัดไป"
#: editor/filesystem_dock.cpp
msgid "Re-Scan Filesystem"
@@ -3873,13 +3876,12 @@ msgid "Move"
msgstr "ย้าย"
#: editor/filesystem_dock.cpp
-#, fuzzy
msgid "There is already file or folder with the same name in this location."
-msgstr "มีโฟลเดอร์ชื่อเดียวà¸à¸±à¸™à¸­à¸¢à¸¹à¹ˆà¹à¸¥à¹‰à¸§"
+msgstr "มีไฟล์หรือโฟลเดอร์ชื่อเดียวà¸à¸±à¸™à¸­à¸¢à¸¹à¹ˆà¹à¸¥à¹‰à¸§"
#: editor/filesystem_dock.cpp
msgid "Overwrite"
-msgstr ""
+msgstr "เขียนทับ"
#: editor/filesystem_dock.cpp
#, fuzzy
@@ -3891,19 +3893,16 @@ msgid "Create Script"
msgstr "สร้างสคริปต์"
#: editor/find_in_files.cpp editor/plugins/script_editor_plugin.cpp
-#, fuzzy
msgid "Find in Files"
-msgstr "ค้นหา tile"
+msgstr "ค้นหาในไฟล์"
#: editor/find_in_files.cpp
-#, fuzzy
msgid "Find:"
-msgstr "ค้นหา"
+msgstr "ค้นหา: "
#: editor/find_in_files.cpp
-#, fuzzy
msgid "Folder:"
-msgstr "ซ่อน"
+msgstr "โฟลเดอร์: "
#: editor/find_in_files.cpp
#, fuzzy
@@ -3930,29 +3929,24 @@ msgid "Cancel"
msgstr "ยà¸à¹€à¸¥à¸´à¸"
#: editor/find_in_files.cpp
-#, fuzzy
msgid "Find: "
-msgstr "ค้นหา"
+msgstr "ค้นหา: "
#: editor/find_in_files.cpp
-#, fuzzy
msgid "Replace: "
-msgstr "à¹à¸—นที่"
+msgstr "à¹à¸—นที่: "
#: editor/find_in_files.cpp
-#, fuzzy
msgid "Replace all (no undo)"
-msgstr "à¹à¸—นที่ทั้งหมด"
+msgstr "à¹à¸—นที่ทั้งหมด(à¹à¸à¹‰à¹‰à¹„ขไม่ได้)"
#: editor/find_in_files.cpp
-#, fuzzy
msgid "Searching..."
-msgstr "à¸à¸³à¸¥à¸±à¸‡à¸šà¸±à¸™à¸—ึà¸..."
+msgstr "à¸à¸³à¸¥à¸±à¸‡à¸„้นหา..."
#: editor/find_in_files.cpp
-#, fuzzy
msgid "Search complete"
-msgstr "ค้นหาคำ"
+msgstr "ค้นหาสำเร็จ"
#: editor/groups_editor.cpp
msgid "Add to Group"
@@ -3973,14 +3967,12 @@ msgid "Invalid group name."
msgstr "ชื่อผิดพลาด"
#: editor/groups_editor.cpp
-#, fuzzy
msgid "Rename Group"
-msgstr "à¸à¸¥à¸¸à¹ˆà¸¡"
+msgstr "เปลี่ยนชื่อà¸à¸£à¸¸à¹Šà¸›"
#: editor/groups_editor.cpp
-#, fuzzy
msgid "Delete Group"
-msgstr "ลบเลย์เอาต์"
+msgstr "ลบà¸à¸£à¸¸à¹Šà¸›"
#: editor/groups_editor.cpp editor/node_dock.cpp
msgid "Groups"
@@ -3997,23 +3989,20 @@ msgid "Filter nodes"
msgstr "ตัวà¸à¸£à¸­à¸‡"
#: editor/groups_editor.cpp
-#, fuzzy
msgid "Nodes in Group"
-msgstr "à¹à¸à¹‰à¹„ขà¸à¸¥à¸¸à¹ˆà¸¡"
+msgstr "โหนดในà¸à¸£à¸¸à¹Šà¸›"
#: editor/groups_editor.cpp
msgid "Empty groups will be automatically removed."
msgstr ""
#: editor/groups_editor.cpp
-#, fuzzy
msgid "Group Editor"
-msgstr "เปิดตัวà¹à¸à¹‰à¹„ขสคริปต์"
+msgstr "ตัวà¹à¸à¹‰à¹„ขà¸à¸£à¸¸à¹Šà¸›"
#: editor/groups_editor.cpp
-#, fuzzy
msgid "Manage Groups"
-msgstr "à¸à¸¥à¸¸à¹ˆà¸¡"
+msgstr "จัดà¸à¸²à¸£à¸à¸£à¸¸à¹Šà¸›"
#: editor/import/resource_importer_scene.cpp
msgid "Import as Single Scene"
@@ -4225,33 +4214,28 @@ msgid "Select a single node to edit its signals and groups."
msgstr "เลือà¸à¹‚หนดเพื่อà¹à¸à¹‰à¹„ขสัà¸à¸à¸²à¸“à¹à¸¥à¸°à¸à¸¥à¸¸à¹ˆà¸¡"
#: editor/plugin_config_dialog.cpp
-#, fuzzy
msgid "Edit a Plugin"
-msgstr "à¹à¸à¹‰à¹„ขรูปหลายเหลี่ยม"
+msgstr "à¹à¸à¹‰à¹„ขปลั๊à¸à¸­à¸´à¸™"
#: editor/plugin_config_dialog.cpp
-#, fuzzy
msgid "Create a Plugin"
-msgstr "สร้าง C# solution"
+msgstr "สร้างปลั๊à¸à¸­à¸´à¸™"
#: editor/plugin_config_dialog.cpp
-#, fuzzy
msgid "Plugin Name:"
-msgstr "ปลั๊à¸à¸­à¸´à¸™"
+msgstr "ชื่อปลั๊à¸à¸­à¸´à¸™"
#: editor/plugin_config_dialog.cpp
msgid "Subfolder:"
-msgstr ""
+msgstr "โฟลเดอร์ย่อย: "
#: editor/plugin_config_dialog.cpp editor/script_create_dialog.cpp
-#, fuzzy
msgid "Language:"
-msgstr "ภาษา"
+msgstr "ภาษา: "
#: editor/plugin_config_dialog.cpp
-#, fuzzy
msgid "Script Name:"
-msgstr "สคริปต์ถูà¸à¸•à¹‰à¸­à¸‡"
+msgstr "ชื่อสคริปต์:"
#: editor/plugin_config_dialog.cpp
msgid "Activate now?"
@@ -4259,16 +4243,14 @@ msgstr ""
#: editor/plugins/abstract_polygon_2d_editor.cpp
#: editor/plugins/polygon_2d_editor_plugin.cpp
-#, fuzzy
msgid "Create Polygon"
-msgstr "สร้างรูปหลายเหลี่ยม"
+msgstr "สร้างโพลีà¸à¸­à¸™"
#: editor/plugins/abstract_polygon_2d_editor.cpp
#: editor/plugins/animation_blend_space_1d_editor.cpp
#: editor/plugins/animation_blend_space_2d_editor.cpp
-#, fuzzy
msgid "Create points."
-msgstr "ลบจุด"
+msgstr "สร้างจุด"
#: editor/plugins/abstract_polygon_2d_editor.cpp
#, fuzzy
@@ -4473,9 +4455,8 @@ msgid "Blend:"
msgstr "ผสม:"
#: editor/plugins/animation_blend_tree_editor_plugin.cpp
-#, fuzzy
msgid "Parameter Changed"
-msgstr "จำนวนครั้งที่เปลี่ยนวัสดุ"
+msgstr "เปลี่ยนพารามิเตอร์"
#: editor/plugins/animation_blend_tree_editor_plugin.cpp
#: editor/plugins/animation_tree_player_editor_plugin.cpp
@@ -4493,25 +4474,22 @@ msgstr "เพิ่มโหนดจาà¸à¸œà¸±à¸‡"
#: editor/plugins/animation_blend_tree_editor_plugin.cpp
#: editor/plugins/visual_shader_editor_plugin.cpp
-#, fuzzy
msgid "Node Moved"
-msgstr "โหมดเคลื่อนย้าย"
+msgstr "ย้ายโหนดเรียบร้อย"
#: editor/plugins/animation_blend_tree_editor_plugin.cpp
msgid "Unable to connect, port may be in use or connection may be invalid."
-msgstr ""
+msgstr "เชื่อมต่อไม่ได้ พอร์ตถูà¸à¹ƒà¸Šà¹‰à¸«à¸£à¸·à¸­à¸¡à¸µà¸„วามผิดพลาด"
#: editor/plugins/animation_blend_tree_editor_plugin.cpp
#: editor/plugins/visual_shader_editor_plugin.cpp
-#, fuzzy
msgid "Nodes Connected"
-msgstr "เชื่อมต่อà¹à¸¥à¹‰à¸§"
+msgstr "เชื่อมต่อโหนดà¹à¸¥à¹‰à¸§"
#: editor/plugins/animation_blend_tree_editor_plugin.cpp
#: editor/plugins/visual_shader_editor_plugin.cpp
-#, fuzzy
msgid "Nodes Disconnected"
-msgstr "à¸à¸²à¸£à¹€à¸Šà¸·à¹ˆà¸­à¸¡à¸•à¹ˆà¸­à¸ªà¸´à¹‰à¸™à¸ªà¸¸à¸”"
+msgstr "ตัดà¸à¸²à¸£à¹€à¸Šà¸·à¹ˆà¸­à¸¡à¸•à¹ˆà¸­à¹‚หนดà¹à¸¥à¹‰à¸§"
#: editor/plugins/animation_blend_tree_editor_plugin.cpp
#, fuzzy
@@ -5140,9 +5118,8 @@ msgid "Downloading (%s / %s)..."
msgstr "à¸à¸³à¸¥à¸±à¸‡à¸”าวน์โหลด"
#: editor/plugins/asset_library_editor_plugin.cpp
-#, fuzzy
msgid "Downloading..."
-msgstr "à¸à¸³à¸¥à¸±à¸‡à¸”าวน์โหลด"
+msgstr "à¸à¸³à¸¥à¸±à¸‡à¸”าวน์โหลด..."
#: editor/plugins/asset_library_editor_plugin.cpp
msgid "Resolving..."
@@ -5157,9 +5134,8 @@ msgid "Idle"
msgstr "พร้อมใช้งาน"
#: editor/plugins/asset_library_editor_plugin.cpp
-#, fuzzy
msgid "Install..."
-msgstr "ติดตั้ง"
+msgstr "ติดตั้ง..."
#: editor/plugins/asset_library_editor_plugin.cpp
msgid "Retry"
@@ -5205,9 +5181,8 @@ msgid "First"
msgstr "à¹à¸£à¸à¸ªà¸¸à¸”"
#: editor/plugins/asset_library_editor_plugin.cpp
-#, fuzzy
msgid "Previous"
-msgstr "à¹à¸—็บà¸à¹ˆà¸­à¸™à¸«à¸™à¹‰à¸²"
+msgstr "à¸à¹ˆà¸­à¸™à¸«à¸™à¹‰à¸²"
#: editor/plugins/asset_library_editor_plugin.cpp
msgid "Next"
@@ -5215,7 +5190,7 @@ msgstr "ต่อไป"
#: editor/plugins/asset_library_editor_plugin.cpp
msgid "Last"
-msgstr ""
+msgstr "ท้ายสุด"
#: editor/plugins/asset_library_editor_plugin.cpp
msgid "All"
@@ -5226,14 +5201,12 @@ msgid "No results for \"%s\"."
msgstr ""
#: editor/plugins/asset_library_editor_plugin.cpp
-#, fuzzy
msgid "Import..."
-msgstr "นำเข้าอีà¸à¸„รั้ง..."
+msgstr "นำเข้า..."
#: editor/plugins/asset_library_editor_plugin.cpp
-#, fuzzy
msgid "Plugins..."
-msgstr "ปลั๊à¸à¸­à¸´à¸™"
+msgstr "ปลั๊à¸à¸­à¸´à¸™..."
#: editor/plugins/asset_library_editor_plugin.cpp editor/project_manager.cpp
msgid "Sort:"
@@ -5249,9 +5222,8 @@ msgid "Site:"
msgstr "ไซต์:"
#: editor/plugins/asset_library_editor_plugin.cpp
-#, fuzzy
msgid "Support"
-msgstr "à¸à¸²à¸£à¸ªà¸™à¸±à¸šà¸ªà¸™à¸¸à¸™..."
+msgstr "สนับสนุน..."
#: editor/plugins/asset_library_editor_plugin.cpp
msgid "Official"
@@ -5262,9 +5234,8 @@ msgid "Testing"
msgstr "ทดสอบ"
#: editor/plugins/asset_library_editor_plugin.cpp
-#, fuzzy
msgid "Loading..."
-msgstr "โหลด"
+msgstr "à¸à¸³à¸¥à¸±à¸‡à¹‚หลด..."
#: editor/plugins/asset_library_editor_plugin.cpp
msgid "Assets ZIP File"
@@ -5957,6 +5928,23 @@ msgstr "Mask à¸à¸²à¸£à¸›à¸°à¸—ุ"
#: editor/plugins/cpu_particles_2d_editor_plugin.cpp
#: editor/plugins/particles_2d_editor_plugin.cpp
+#, fuzzy
+msgid "Solid Pixels"
+msgstr "Snap (พิà¸à¹€à¸‹à¸¥):"
+
+#: 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
+#, fuzzy
+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 "ใช้สีพิà¸à¹€à¸‹à¸¥"
@@ -6971,9 +6959,8 @@ msgid "Open..."
msgstr "เปิด"
#: editor/plugins/script_editor_plugin.cpp
-#, fuzzy
msgid "Reopen Closed Script"
-msgstr "เปิดสคริปต์"
+msgstr "เปิดสคริปต์อีà¸à¸£à¸­à¸š"
#: editor/plugins/script_editor_plugin.cpp
msgid "Save All"
@@ -6988,7 +6975,6 @@ msgid "Copy Script Path"
msgstr "คัดลอà¸à¸•à¸³à¹à¸«à¸™à¹ˆà¸‡à¸ªà¸„ริปต์"
#: editor/plugins/script_editor_plugin.cpp
-#, fuzzy
msgid "History Previous"
msgstr "ประวัติà¸à¹ˆà¸­à¸™à¸«à¸™à¹‰à¸²"
@@ -9215,15 +9201,15 @@ msgstr ""
#: editor/plugins/visual_shader_editor_plugin.cpp
msgid "Returns the arc-sine of the parameter."
-msgstr ""
+msgstr "คืนค่า arc sin ของพารามิเตอร์"
#: editor/plugins/visual_shader_editor_plugin.cpp
msgid "Returns the inverse hyperbolic sine of the parameter."
-msgstr ""
+msgstr "คืนค่า arc sinh ของพารามิเตอร์"
#: editor/plugins/visual_shader_editor_plugin.cpp
msgid "Returns the arc-tangent of the parameter."
-msgstr ""
+msgstr "คืนค่า arc tan ของพารามิเตอร์"
#: editor/plugins/visual_shader_editor_plugin.cpp
msgid "Returns the arc-tangent of the parameters."
@@ -9861,6 +9847,10 @@ msgid "Export PCK/Zip"
msgstr "ส่งออภPCK/Zip"
#: editor/project_export.cpp
+msgid "Export Project"
+msgstr "ส่งออà¸à¹‚ปรเจà¸à¸•à¹Œ"
+
+#: editor/project_export.cpp
#, fuzzy
msgid "Export mode?"
msgstr "วิธีà¸à¸²à¸£à¸ªà¹ˆà¸‡à¸­à¸­à¸:"
@@ -9958,10 +9948,6 @@ msgid "Couldn't create project.godot in project path."
msgstr "สร้างไฟล์ project.godot ไม่ได้"
#: editor/project_manager.cpp
-msgid "The following files failed extraction from package:"
-msgstr "ผิดพลาดขณะà¹à¸¢à¸à¹„ฟล์ต่อไปนี้จาà¸à¹à¸žà¸„เà¸à¸ˆ:"
-
-#: editor/project_manager.cpp
msgid "Rename Project"
msgstr "เปลี่ยนชื่อโปรเจà¸à¸•à¹Œ"
@@ -11221,6 +11207,11 @@ msgstr "โหลดสคริปต์จาà¸à¸”ิสà¸à¹Œ"
#: editor/script_create_dialog.cpp
#, fuzzy
+msgid "Script file already exists."
+msgstr "มีà¸à¸²à¸£à¸à¸£à¸°à¸—ำ '%s' อยู่à¹à¸¥à¹‰à¸§!"
+
+#: editor/script_create_dialog.cpp
+#, fuzzy
msgid "Class Name:"
msgstr "ชื่อคลาส"
@@ -12861,7 +12852,14 @@ msgid "This node has been deprecated. Use AnimationTree instead."
msgstr ""
#: scene/gui/color_picker.cpp
-msgid "Pick a color from the screen."
+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
@@ -12981,6 +12979,9 @@ msgstr ""
msgid "Constants cannot be modified."
msgstr ""
+#~ msgid "Password:"
+#~ msgstr "รหัสผ่าน:"
+
#~ msgid "Pause the scene"
#~ msgstr "หยุดชั่วคราว"
@@ -13256,9 +13257,6 @@ msgstr ""
#~ msgid "Create folder"
#~ msgstr "สร้างโฟลเดอร์"
-#~ msgid "Already existing"
-#~ msgstr "มีอยู่à¸à¹ˆà¸­à¸™à¹à¸¥à¹‰à¸§"
-
#, fuzzy
#~ msgid "Custom Node"
#~ msgstr "ตัดโหนด"
@@ -13307,10 +13305,6 @@ msgstr ""
#~ msgstr "PathFollow2D จะทำงานได้ต้องเป็นโหนดลูà¸à¸‚องโหนด Path2D"
#, fuzzy
-#~ msgid "Split already exists."
-#~ msgstr "มีà¸à¸²à¸£à¸à¸£à¸°à¸—ำ '%s' อยู่à¹à¸¥à¹‰à¸§!"
-
-#, fuzzy
#~ msgid "Add Split"
#~ msgstr "เพิ่มจุด"
diff --git a/editor/translations/tr.po b/editor/translations/tr.po
index 7be506be25..e43c4e7211 100644
--- a/editor/translations/tr.po
+++ b/editor/translations/tr.po
@@ -1228,10 +1228,24 @@ msgid "Error opening package file, not in ZIP format."
msgstr "Paket dosyası açılırken hata oluştu, zip formatında değil."
#: editor/editor_asset_installer.cpp
+#, fuzzy
+msgid "%s (Already Exists)"
+msgstr "Zaten mevcut"
+
+#: editor/editor_asset_installer.cpp
msgid "Uncompressing Assets"
msgstr "Varlıklar Çıkartılıyor"
#: editor/editor_asset_installer.cpp editor/project_manager.cpp
+msgid "The following files failed extraction from package:"
+msgstr "Aşağıdaki dosyaların, çıkından ayıklanma işlemi başarısız oldu:"
+
+#: editor/editor_asset_installer.cpp
+#, fuzzy
+msgid "And %s more files."
+msgstr "%d daha fazla dosyalar"
+
+#: editor/editor_asset_installer.cpp editor/project_manager.cpp
msgid "Package installed successfully!"
msgstr "Paket Başarı ile Kuruldu!"
@@ -1240,6 +1254,11 @@ msgstr "Paket Başarı ile Kuruldu!"
msgid "Success!"
msgstr "Başarılı!"
+#: editor/editor_asset_installer.cpp
+#, fuzzy
+msgid "Package Contents:"
+msgstr "İçerikler:"
+
#: editor/editor_asset_installer.cpp editor/editor_node.cpp
msgid "Install"
msgstr "Kur"
@@ -1378,6 +1397,11 @@ msgid "Invalid file, not an audio bus layout."
msgstr "Geçersiz dosya, bu bir audio bus yerleşim düzeni değil."
#: editor/editor_audio_buses.cpp
+#, fuzzy
+msgid "Error saving file: %s"
+msgstr "Dosya kaydedilirken hata!"
+
+#: editor/editor_audio_buses.cpp
msgid "Add Bus"
msgstr "Bus ekle"
@@ -2173,10 +2197,6 @@ msgid "New Window"
msgstr "Yeni Pencere"
#: editor/editor_node.cpp
-msgid "Project export failed with error code %d."
-msgstr "Proje dışa aktarımı %d hata koduyla başarısız."
-
-#: editor/editor_node.cpp
msgid "Imported resources can't be saved."
msgstr "İçe aktarılmış kaynaklar kaydedilemez."
@@ -3084,10 +3104,6 @@ msgstr "Şablonları Zip Dosyasından İçeri Aktar"
msgid "Template Package"
msgstr "Dışa Aktarım Şablonu Yöneticisi"
-#: editor/editor_node.cpp editor/project_export.cpp
-msgid "Export Project"
-msgstr "Projeyi Dışa Aktar"
-
#: editor/editor_node.cpp
msgid "Export Library"
msgstr "Betikevini Dışa Aktar"
@@ -3097,10 +3113,6 @@ msgid "Merge With Existing"
msgstr "Var Olanla BirleÅŸtir"
#: editor/editor_node.cpp
-msgid "Password:"
-msgstr "Gizyazı:"
-
-#: editor/editor_node.cpp
msgid "Open & Run a Script"
msgstr "Aç & Bir Betik Çalıştır"
@@ -5759,6 +5771,23 @@ msgstr "Emisyon Maskesi"
#: editor/plugins/cpu_particles_2d_editor_plugin.cpp
#: editor/plugins/particles_2d_editor_plugin.cpp
+#, fuzzy
+msgid "Solid Pixels"
+msgstr "Sıkıştır (Pikselleri): "
+
+#: 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
+#, fuzzy
+msgid "Directed Border Pixels"
+msgstr "Dizinler & Dosyalar:"
+
+#: editor/plugins/cpu_particles_2d_editor_plugin.cpp
+#: editor/plugins/particles_2d_editor_plugin.cpp
msgid "Capture from Pixel"
msgstr "Pikselden Yakala"
@@ -9498,6 +9527,10 @@ msgid "Export PCK/Zip"
msgstr "PCK/Zip Dışa Aktar"
#: editor/project_export.cpp
+msgid "Export Project"
+msgstr "Projeyi Dışa Aktar"
+
+#: editor/project_export.cpp
#, fuzzy
msgid "Export mode?"
msgstr "Dışa Aktarma Biçimi:"
@@ -9594,10 +9627,6 @@ msgid "Couldn't create project.godot in project path."
msgstr "proje.godot proje yolunda oluşturulamadı."
#: editor/project_manager.cpp
-msgid "The following files failed extraction from package:"
-msgstr "Aşağıdaki dosyaların, çıkından ayıklanma işlemi başarısız oldu:"
-
-#: editor/project_manager.cpp
msgid "Rename Project"
msgstr "Projeyi Yeniden Adlandır"
@@ -10868,6 +10897,11 @@ msgstr "Mevcut betik dosyasını yükle"
#: editor/script_create_dialog.cpp
#, fuzzy
+msgid "Script file already exists."
+msgstr "Ä°ÅŸlem '%s' zaten var!"
+
+#: editor/script_create_dialog.cpp
+#, fuzzy
msgid "Class Name:"
msgstr "Sınıf İsmi"
@@ -12569,7 +12603,14 @@ msgid "This node has been deprecated. Use AnimationTree instead."
msgstr ""
#: scene/gui/color_picker.cpp
-msgid "Pick a color from the screen."
+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
@@ -12691,6 +12732,12 @@ msgstr "Değişkenler yalnızca tepe işlevinde atanabilir."
msgid "Constants cannot be modified."
msgstr "Sabit deÄŸerler deÄŸiÅŸtirilemez."
+#~ msgid "Project export failed with error code %d."
+#~ msgstr "Proje dışa aktarımı %d hata koduyla başarısız."
+
+#~ msgid "Password:"
+#~ msgstr "Gizyazı:"
+
#~ msgid "Pause the scene"
#~ msgstr "Sahneyi duraklat"
@@ -12973,9 +13020,6 @@ msgstr "Sabit deÄŸerler deÄŸiÅŸtirilemez."
#~ msgid "Create folder"
#~ msgstr "Klasör Oluştur"
-#~ msgid "Already existing"
-#~ msgstr "Zaten mevcut"
-
#, fuzzy
#~ msgid "Custom Node"
#~ msgstr "Düğümleri Kes"
@@ -13025,10 +13069,6 @@ msgstr "Sabit deÄŸerler deÄŸiÅŸtirilemez."
#~ "PathFollow2D yalnızca Path2D düğümünün çocuğu olarak ayarlanınca çalışır."
#, fuzzy
-#~ msgid "Split already exists."
-#~ msgstr "Ä°ÅŸlem '%s' zaten var!"
-
-#, fuzzy
#~ msgid "Add Split"
#~ msgstr "Nokta Ekle"
diff --git a/editor/translations/uk.po b/editor/translations/uk.po
index 4759a2b209..227e219c54 100644
--- a/editor/translations/uk.po
+++ b/editor/translations/uk.po
@@ -3,7 +3,7 @@
# Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md).
# This file is distributed under the same license as the Godot source code.
# Aleksandr <XpycT.TOP@gmail.com>, 2017.
-# Yuri Chornoivan <yurchor@ukr.net>, 2018, 2019.
+# Yuri Chornoivan <yurchor@ukr.net>, 2018, 2019, 2020.
# Ðндрій Бандура <andriykopanytsia@gmail.com>, 2018.
# Гидеон Теон <t.kudely94@gmail.com>, 2017.
# МакÑим Якимчук <xpinovo@gmail.com>, 2018, 2019.
@@ -12,12 +12,13 @@
# Kirill Omelchenko <kirill.omelchenko@gmail.com>, 2018.
# ÐлекÑандр <ol-vin@mail.ru>, 2018.
# Богдан Матвіїв <bomtvv@gmail.com>, 2019.
+# Tymofij Lytvynenko <till.svit@gmail.com>, 2020.
msgid ""
msgstr ""
"Project-Id-Version: Ukrainian (Godot Engine)\n"
"POT-Creation-Date: \n"
-"PO-Revision-Date: 2019-12-23 17:07+0000\n"
-"Last-Translator: Yuri Chornoivan <yurchor@ukr.net>\n"
+"PO-Revision-Date: 2020-01-03 21:21+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"
@@ -431,6 +432,8 @@ msgstr "Ðе можна додавати нові доріжки без коре
#: editor/animation_track_editor.cpp
msgid "Invalid track for Bezier (no suitable sub-properties)"
msgstr ""
+"Ðекоректна Ñ‚Ñ€Ð°Ñ”ÐºÑ‚Ð¾Ñ€Ñ–Ñ Ð´Ð»Ñ ÐºÑ€Ð¸Ð²Ð¾Ñ— Безьє (немає відповідних підлеглих "
+"влаÑтивоÑтей)"
#: editor/animation_track_editor.cpp
msgid "Add Bezier Track"
@@ -1193,7 +1196,7 @@ msgstr "Ð’ÑÑ– компоненти"
#: editor/editor_about.cpp
msgid "Components"
-msgstr "Компоненти"
+msgstr "Складники"
#: editor/editor_about.cpp
msgid "Licenses"
@@ -1204,10 +1207,24 @@ msgid "Error opening package file, not in ZIP format."
msgstr "Помилка під Ñ‡Ð°Ñ Ñпроби відкрити файл пакунка — дані не у форматі zip."
#: editor/editor_asset_installer.cpp
+#, fuzzy
+msgid "%s (Already Exists)"
+msgstr "Вже Ñ–Ñнує"
+
+#: editor/editor_asset_installer.cpp
msgid "Uncompressing Assets"
msgstr "Ð Ð¾Ð·Ð¿Ð°ÐºÐ¾Ð²ÑƒÐ²Ð°Ð½Ð½Ñ Ð°ÐºÑ‚Ð¸Ð²Ñ–Ð²"
#: editor/editor_asset_installer.cpp editor/project_manager.cpp
+msgid "The following files failed extraction from package:"
+msgstr "Ðе вдалоÑÑ Ð²Ð¸Ð´Ð¾Ð±ÑƒÑ‚Ð¸ такі файли з пакунка:"
+
+#: editor/editor_asset_installer.cpp
+#, fuzzy
+msgid "And %s more files."
+msgstr "%d більше файлів"
+
+#: editor/editor_asset_installer.cpp editor/project_manager.cpp
msgid "Package installed successfully!"
msgstr "Пакунок уÑпішно вÑтановлено!"
@@ -1216,6 +1233,11 @@ msgstr "Пакунок уÑпішно вÑтановлено!"
msgid "Success!"
msgstr "УÑпіх!"
+#: editor/editor_asset_installer.cpp
+#, fuzzy
+msgid "Package Contents:"
+msgstr "ЗміÑÑ‚:"
+
#: editor/editor_asset_installer.cpp editor/editor_node.cpp
msgid "Install"
msgstr "Ð’Ñтановити"
@@ -1354,6 +1376,11 @@ msgid "Invalid file, not an audio bus layout."
msgstr "ÐеприпуÑтимий файл, це не ÐºÐ¾Ð¼Ð¿Ð¾Ð½ÑƒÐ²Ð°Ð½Ð½Ñ Ð°ÑƒÐ´Ñ–Ð¾-шини."
#: editor/editor_audio_buses.cpp
+#, fuzzy
+msgid "Error saving file: %s"
+msgstr "Помилка під Ñ‡Ð°Ñ Ð·Ð±ÐµÑ€ÐµÐ¶ÐµÐ½Ð½Ñ Ñ„Ð°Ð¹Ð»Ð°!"
+
+#: editor/editor_audio_buses.cpp
msgid "Add Bus"
msgstr "Додати шину"
@@ -2006,9 +2033,8 @@ msgid "Case Sensitive"
msgstr "ЧутливіÑÑ‚ÑŒ регіÑтра"
#: editor/editor_help_search.cpp
-#, fuzzy
msgid "Show Hierarchy"
-msgstr "Показати помічники"
+msgstr "Показати ієрархію"
#: editor/editor_help_search.cpp
msgid "Display All"
@@ -2047,9 +2073,8 @@ msgid "Class"
msgstr "КлаÑ"
#: editor/editor_help_search.cpp
-#, fuzzy
msgid "Method"
-msgstr "Методи"
+msgstr "Метод"
#: editor/editor_help_search.cpp editor/plugins/script_text_editor.cpp
msgid "Signal"
@@ -2060,14 +2085,12 @@ msgid "Constant"
msgstr "Сталий"
#: editor/editor_help_search.cpp
-#, fuzzy
msgid "Property"
-msgstr "ВлаÑтивіÑÑ‚ÑŒ:"
+msgstr "ВлаÑтивіÑÑ‚ÑŒ"
#: editor/editor_help_search.cpp
-#, fuzzy
msgid "Theme Property"
-msgstr "ВлаÑтивоÑÑ‚Ñ– теми"
+msgstr "ВлаÑтивіÑÑ‚ÑŒ теми"
#: editor/editor_inspector.cpp editor/project_settings_editor.cpp
msgid "Property:"
@@ -2150,10 +2173,6 @@ msgid "New Window"
msgstr "Ðове вікно"
#: editor/editor_node.cpp
-msgid "Project export failed with error code %d."
-msgstr "Ðе вдалоÑÑ ÐµÐºÑпортувати проєкт, код помилки — %d."
-
-#: editor/editor_node.cpp
msgid "Imported resources can't be saved."
msgstr "Ðеможливо зберегти імпортовані реÑурÑи."
@@ -3071,10 +3090,6 @@ msgstr "Імпортувати шаблони з ZIP-файлу"
msgid "Template Package"
msgstr "Пакунок шаблонів"
-#: editor/editor_node.cpp editor/project_export.cpp
-msgid "Export Project"
-msgstr "ЕкÑпортувати проєкт"
-
#: editor/editor_node.cpp
msgid "Export Library"
msgstr "ЕкÑпортувати бібліотеку"
@@ -3084,10 +3099,6 @@ msgid "Merge With Existing"
msgstr "Об'єднати з Ñ–Ñнуючим"
#: editor/editor_node.cpp
-msgid "Password:"
-msgstr "Пароль:"
-
-#: editor/editor_node.cpp
msgid "Open & Run a Script"
msgstr "Відкрити Ñ– запуÑтити Ñкрипт"
@@ -3451,11 +3462,13 @@ msgstr "ІмпортуваннÑ:"
#: editor/export_template_manager.cpp
msgid "Error getting the list of mirrors."
-msgstr ""
+msgstr "Помилка під Ñ‡Ð°Ñ Ð¾Ñ‚Ñ€Ð¸Ð¼Ð°Ð½Ð½Ñ ÑпиÑку дзеркал."
#: editor/export_template_manager.cpp
msgid "Error parsing JSON of mirror list. Please report this issue!"
msgstr ""
+"Помилка під Ñ‡Ð°Ñ Ð¾Ð±Ñ€Ð¾Ð±ÐºÐ¸ JSON ÑпиÑку дзеркал. Будь лаÑка, повідомте про цю "
+"ваду!"
#: editor/export_template_manager.cpp
msgid ""
@@ -4645,9 +4658,8 @@ msgid "Move Node"
msgstr "ПереÑунути вузол"
#: editor/plugins/animation_state_machine_editor.cpp
-#, fuzzy
msgid "Transition exists!"
-msgstr "Перехід: "
+msgstr "ІÑнує перехід!"
#: editor/plugins/animation_state_machine_editor.cpp
msgid "Add Transition"
@@ -5725,6 +5737,23 @@ msgstr "МаÑка випромінюваннÑ"
#: editor/plugins/cpu_particles_2d_editor_plugin.cpp
#: editor/plugins/particles_2d_editor_plugin.cpp
+#, fuzzy
+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
+#, fuzzy
+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 "Захопити з пікÑелÑ"
@@ -5950,18 +5979,19 @@ msgstr "Розмір обведеннÑ:"
#: editor/plugins/mesh_instance_editor_plugin.cpp
msgid "UV Channel Debug"
-msgstr ""
+msgstr "ДіагноÑтика UV-каналу"
#: editor/plugins/mesh_library_editor_plugin.cpp
msgid "Remove item %d?"
msgstr "Ð’Ð¸Ð´Ð°Ð»ÐµÐ½Ð½Ñ ÐµÐ»ÐµÐ¼ÐµÐ½Ñ‚Ð° %d?"
#: editor/plugins/mesh_library_editor_plugin.cpp
-#, fuzzy
msgid ""
"Update from existing scene?:\n"
"%s"
-msgstr "Оновити зі Ñцени"
+msgstr ""
+"Оновити з наÑвної Ñцени?\n"
+"%s"
#: editor/plugins/mesh_library_editor_plugin.cpp
msgid "Mesh Library"
@@ -7516,9 +7546,8 @@ msgid "Create Mesh2D"
msgstr "Створити Mesh2D"
#: editor/plugins/sprite_editor_plugin.cpp
-#, fuzzy
msgid "Mesh2D Preview"
-msgstr "Ð¡Ñ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ð¿Ð¾Ð¿ÐµÑ€ÐµÐ´Ð½ÑŒÐ¾Ð³Ð¾ переглÑду Ñітки"
+msgstr "Попередній переглÑд плоÑкої Ñітки"
#: editor/plugins/sprite_editor_plugin.cpp
msgid "Create Polygon2D"
@@ -7526,25 +7555,23 @@ msgstr "Створити Polygon2D"
#: editor/plugins/sprite_editor_plugin.cpp
msgid "Polygon2D Preview"
-msgstr ""
+msgstr "Попередній переглÑд плоÑкого багатокутника"
#: editor/plugins/sprite_editor_plugin.cpp
msgid "Create CollisionPolygon2D"
msgstr "Створити CollisionPolygon2D"
#: editor/plugins/sprite_editor_plugin.cpp
-#, fuzzy
msgid "CollisionPolygon2D Preview"
-msgstr "Створити CollisionPolygon2D"
+msgstr "Попередній переглÑд CollisionPolygon2D"
#: editor/plugins/sprite_editor_plugin.cpp
msgid "Create LightOccluder2D"
msgstr "Створити LightOccluder2D"
#: editor/plugins/sprite_editor_plugin.cpp
-#, fuzzy
msgid "LightOccluder2D Preview"
-msgstr "Створити LightOccluder2D"
+msgstr "Попередній переглÑд LightOccluder2D"
#: editor/plugins/sprite_editor_plugin.cpp
msgid "Sprite is empty!"
@@ -7625,9 +7652,8 @@ msgid "Add Frame"
msgstr "Додати кадр"
#: editor/plugins/sprite_frames_editor_plugin.cpp
-#, fuzzy
msgid "Unable to load images"
-msgstr "Ðе вдалоÑÑ Ð·Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶Ð¸Ñ‚Ð¸ реÑурÑ."
+msgstr "Ðе вдалоÑÑ Ð·Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶Ð¸Ñ‚Ð¸ зображеннÑ"
#: editor/plugins/sprite_frames_editor_plugin.cpp
msgid "ERROR: Couldn't load frame resource!"
@@ -8319,14 +8345,12 @@ msgid "Edit Tile Z Index"
msgstr "Редагувати z-Ñ–Ð½Ð´ÐµÐºÑ Ð¿Ð»Ð¸Ñ‚ÐºÐ¸"
#: editor/plugins/tile_set_editor_plugin.cpp
-#, fuzzy
msgid "Make Convex"
-msgstr "Зробити полігон опуклим"
+msgstr "Зробити опуклим"
#: editor/plugins/tile_set_editor_plugin.cpp
-#, fuzzy
msgid "Make Concave"
-msgstr "Зробити полігон увігнутим"
+msgstr "Зробити увігнутим"
#: editor/plugins/tile_set_editor_plugin.cpp
msgid "Create Collision Polygon"
@@ -9484,6 +9508,10 @@ msgid "Export PCK/Zip"
msgstr "ЕкÑпортувати PCK/Zip"
#: editor/project_export.cpp
+msgid "Export Project"
+msgstr "ЕкÑпортувати проєкт"
+
+#: editor/project_export.cpp
msgid "Export mode?"
msgstr "Режим екÑпортуваннÑ?"
@@ -9576,10 +9604,6 @@ msgid "Couldn't create project.godot in project path."
msgstr "Ðе вдалоÑÑ Ñтворити project.godot у каталозі проєкту."
#: editor/project_manager.cpp
-msgid "The following files failed extraction from package:"
-msgstr "Ðе вдалоÑÑ Ð²Ð¸Ð´Ð¾Ð±ÑƒÑ‚Ð¸ такі файли з пакунка:"
-
-#: editor/project_manager.cpp
msgid "Rename Project"
msgstr "Перейменувати проєкт"
@@ -10819,6 +10843,11 @@ msgid "Will load an existing script file."
msgstr "Завантажити наÑвний файл Ñкрипту."
#: editor/script_create_dialog.cpp
+#, fuzzy
+msgid "Script file already exists."
+msgstr "Поділ вже Ñ–Ñнує."
+
+#: editor/script_create_dialog.cpp
msgid "Class Name:"
msgstr "Ðазва клаÑу:"
@@ -11269,9 +11298,8 @@ msgid "Cursor Clear Rotation"
msgstr "ЗнÑти Ð¾Ð±ÐµÑ€Ñ‚Ð°Ð½Ð½Ñ Ð· вказівника"
#: modules/gridmap/grid_map_editor_plugin.cpp
-#, fuzzy
msgid "Paste Selects"
-msgstr "Витерти позначене"
+msgstr "Ð’ÑтавлÑÐ½Ð½Ñ Ð¿Ð¾Ð·Ð½Ð°Ñ‡Ð°Ñ”"
#: modules/gridmap/grid_map_editor_plugin.cpp
msgid "Clear Selection"
@@ -12503,7 +12531,15 @@ msgstr ""
"Цей вузол вважаєтьÑÑ Ð·Ð°Ñтарілим. СкориÑтайтеÑÑ Ð·Ð°Ð¼Ñ–ÑÑ‚ÑŒ нього AnimationTree."
#: scene/gui/color_picker.cpp
-msgid "Pick a color from the screen."
+msgid ""
+"Color: #%s\n"
+"LMB: Set color\n"
+"RMB: Remove preset"
+msgstr ""
+
+#: scene/gui/color_picker.cpp
+#, fuzzy
+msgid "Pick a color from the editor window."
msgstr "Вибрати колір з екрана."
#: scene/gui/color_picker.cpp
@@ -12627,6 +12663,12 @@ msgstr "Змінні величини можна пов'Ñзувати лише
msgid "Constants cannot be modified."
msgstr "Сталі не можна змінювати."
+#~ msgid "Project export failed with error code %d."
+#~ msgstr "Ðе вдалоÑÑ ÐµÐºÑпортувати проєкт, код помилки — %d."
+
+#~ msgid "Password:"
+#~ msgstr "Пароль:"
+
#~ msgid "Identifier segments must be of non-zero length."
#~ msgstr "Сегменти ідентифікатора повинні мати ненульову довжину."
@@ -13098,9 +13140,6 @@ msgstr "Сталі не можна змінювати."
#~ msgid "Create folder"
#~ msgstr "Створити теку"
-#~ msgid "Already existing"
-#~ msgstr "Вже Ñ–Ñнує"
-
#~ msgid "Custom Node"
#~ msgstr "Ðетиповий вузол"
@@ -13149,9 +13188,6 @@ msgstr "Сталі не можна змінювати."
#~ msgid "Split can't form an existing edge."
#~ msgstr "Поділ не може Ñтворювати наÑвного ребра."
-#~ msgid "Split already exists."
-#~ msgstr "Поділ вже Ñ–Ñнує."
-
#~ msgid "Add Split"
#~ msgstr "Додати поділ"
diff --git a/editor/translations/ur_PK.po b/editor/translations/ur_PK.po
index ec8d92827e..e3ebee0a76 100644
--- a/editor/translations/ur_PK.po
+++ b/editor/translations/ur_PK.po
@@ -1174,10 +1174,22 @@ msgid "Error opening package file, not in ZIP format."
msgstr ""
#: editor/editor_asset_installer.cpp
+msgid "%s (Already Exists)"
+msgstr ""
+
+#: editor/editor_asset_installer.cpp
msgid "Uncompressing Assets"
msgstr ""
#: editor/editor_asset_installer.cpp editor/project_manager.cpp
+msgid "The following files failed extraction from package:"
+msgstr ""
+
+#: editor/editor_asset_installer.cpp
+msgid "And %s more files."
+msgstr ""
+
+#: editor/editor_asset_installer.cpp editor/project_manager.cpp
msgid "Package installed successfully!"
msgstr ""
@@ -1186,6 +1198,10 @@ msgstr ""
msgid "Success!"
msgstr ""
+#: editor/editor_asset_installer.cpp
+msgid "Package Contents:"
+msgstr ""
+
#: editor/editor_asset_installer.cpp editor/editor_node.cpp
msgid "Install"
msgstr ""
@@ -1327,6 +1343,10 @@ msgid "Invalid file, not an audio bus layout."
msgstr ""
#: editor/editor_audio_buses.cpp
+msgid "Error saving file: %s"
+msgstr ""
+
+#: editor/editor_audio_buses.cpp
msgid "Add Bus"
msgstr ""
@@ -2125,10 +2145,6 @@ msgid "New Window"
msgstr ""
#: editor/editor_node.cpp
-msgid "Project export failed with error code %d."
-msgstr ""
-
-#: editor/editor_node.cpp
msgid "Imported resources can't be saved."
msgstr ""
@@ -2975,10 +2991,6 @@ msgstr ""
msgid "Template Package"
msgstr ".تمام کا انتخاب"
-#: editor/editor_node.cpp editor/project_export.cpp
-msgid "Export Project"
-msgstr ""
-
#: editor/editor_node.cpp
msgid "Export Library"
msgstr ""
@@ -2988,10 +3000,6 @@ msgid "Merge With Existing"
msgstr ""
#: editor/editor_node.cpp
-msgid "Password:"
-msgstr ""
-
-#: editor/editor_node.cpp
msgid "Open & Run a Script"
msgstr ""
@@ -5621,6 +5629,21 @@ 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 ""
@@ -9341,6 +9364,10 @@ msgid "Export PCK/Zip"
msgstr ""
#: editor/project_export.cpp
+msgid "Export Project"
+msgstr ""
+
+#: editor/project_export.cpp
msgid "Export mode?"
msgstr ""
@@ -9433,10 +9460,6 @@ msgid "Couldn't create project.godot in project path."
msgstr ""
#: editor/project_manager.cpp
-msgid "The following files failed extraction from package:"
-msgstr ""
-
-#: editor/project_manager.cpp
#, fuzzy
msgid "Rename Project"
msgstr ".تمام کا انتخاب"
@@ -10619,6 +10642,10 @@ msgid "Will load an existing script file."
msgstr "سب سکریپشن بنائیں"
#: editor/script_create_dialog.cpp
+msgid "Script file already exists."
+msgstr ""
+
+#: editor/script_create_dialog.cpp
msgid "Class Name:"
msgstr ""
@@ -12182,7 +12209,14 @@ msgid "This node has been deprecated. Use AnimationTree instead."
msgstr ""
#: scene/gui/color_picker.cpp
-msgid "Pick a color from the screen."
+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
diff --git a/editor/translations/vi.po b/editor/translations/vi.po
index 4a733f81ac..6c2bcb20e4 100644
--- a/editor/translations/vi.po
+++ b/editor/translations/vi.po
@@ -1202,10 +1202,24 @@ msgid "Error opening package file, not in ZIP format."
msgstr "Lỗi không thể mở gói, không phải dạng nén."
#: editor/editor_asset_installer.cpp
+#, fuzzy
+msgid "%s (Already Exists)"
+msgstr "Tam giác đã tồn tại."
+
+#: editor/editor_asset_installer.cpp
msgid "Uncompressing Assets"
msgstr "Giải nén Assets"
#: editor/editor_asset_installer.cpp editor/project_manager.cpp
+msgid "The following files failed extraction from package:"
+msgstr ""
+
+#: editor/editor_asset_installer.cpp
+#, fuzzy
+msgid "And %s more files."
+msgstr "%d thêm các tệp tin"
+
+#: editor/editor_asset_installer.cpp editor/project_manager.cpp
msgid "Package installed successfully!"
msgstr "Cài đặt gói thành công!"
@@ -1214,6 +1228,11 @@ msgstr "Cài đặt gói thành công!"
msgid "Success!"
msgstr "Thành công!"
+#: editor/editor_asset_installer.cpp
+#, fuzzy
+msgid "Package Contents:"
+msgstr "Ná»™i dung:"
+
#: editor/editor_asset_installer.cpp editor/editor_node.cpp
msgid "Install"
msgstr "Cài đặt"
@@ -1352,6 +1371,11 @@ msgid "Invalid file, not an audio bus layout."
msgstr ""
#: editor/editor_audio_buses.cpp
+#, fuzzy
+msgid "Error saving file: %s"
+msgstr "Lỗi tải font."
+
+#: editor/editor_audio_buses.cpp
msgid "Add Bus"
msgstr ""
@@ -2144,10 +2168,6 @@ msgid "New Window"
msgstr ""
#: editor/editor_node.cpp
-msgid "Project export failed with error code %d."
-msgstr "Xuất dự án thất bại với mã lỗi %d."
-
-#: editor/editor_node.cpp
msgid "Imported resources can't be saved."
msgstr "Tài nguyên đã nhập không thể lưu."
@@ -3035,10 +3055,6 @@ msgstr "Nhập mẫu vào từ tệp nén ZIP"
msgid "Template Package"
msgstr "Khung project"
-#: editor/editor_node.cpp editor/project_export.cpp
-msgid "Export Project"
-msgstr "Xuất dự án ra"
-
#: editor/editor_node.cpp
msgid "Export Library"
msgstr "Xuất thư viện ra"
@@ -3048,10 +3064,6 @@ msgid "Merge With Existing"
msgstr ""
#: editor/editor_node.cpp
-msgid "Password:"
-msgstr "Mật khẩu:"
-
-#: editor/editor_node.cpp
msgid "Open & Run a Script"
msgstr "Mở & Chạy mã lệnh"
@@ -5695,6 +5707,22 @@ 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
+#, fuzzy
+msgid "Directed Border Pixels"
+msgstr "Các Thư mục và Tệp tin:"
+
+#: editor/plugins/cpu_particles_2d_editor_plugin.cpp
+#: editor/plugins/particles_2d_editor_plugin.cpp
msgid "Capture from Pixel"
msgstr ""
@@ -9461,6 +9489,10 @@ msgid "Export PCK/Zip"
msgstr ""
#: editor/project_export.cpp
+msgid "Export Project"
+msgstr "Xuất dự án ra"
+
+#: editor/project_export.cpp
#, fuzzy
msgid "Export mode?"
msgstr "Nhập từ Node:"
@@ -9555,10 +9587,6 @@ msgid "Couldn't create project.godot in project path."
msgstr ""
#: editor/project_manager.cpp
-msgid "The following files failed extraction from package:"
-msgstr ""
-
-#: editor/project_manager.cpp
msgid "Rename Project"
msgstr ""
@@ -10754,6 +10782,11 @@ msgstr ""
#: editor/script_create_dialog.cpp
#, fuzzy
+msgid "Script file already exists."
+msgstr "Tam giác đã tồn tại."
+
+#: editor/script_create_dialog.cpp
+#, fuzzy
msgid "Class Name:"
msgstr "Lá»›p:"
@@ -12326,7 +12359,14 @@ msgid "This node has been deprecated. Use AnimationTree instead."
msgstr ""
#: scene/gui/color_picker.cpp
-msgid "Pick a color from the screen."
+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
@@ -12435,6 +12475,12 @@ msgstr ""
msgid "Constants cannot be modified."
msgstr "Không thể chỉnh sửa hằng số."
+#~ msgid "Project export failed with error code %d."
+#~ msgstr "Xuất dự án thất bại với mã lỗi %d."
+
+#~ msgid "Password:"
+#~ msgstr "Mật khẩu:"
+
#~ msgid "Pause the scene"
#~ msgstr "Tạm dừng cảnh"
diff --git a/editor/translations/zh_CN.po b/editor/translations/zh_CN.po
index ac9b2e4be6..a1edaeec7e 100644
--- a/editor/translations/zh_CN.po
+++ b/editor/translations/zh_CN.po
@@ -58,12 +58,12 @@
# idleman <1524328475@qq.com>, 2019.
# king <wangding1992@126.com>, 2019.
# silentbird <silentbird520@outlook.com>, 2019.
-# Haoyu Qiu <timothyqiu32@gmail.com>, 2019.
+# Haoyu Qiu <timothyqiu32@gmail.com>, 2019, 2020.
msgid ""
msgstr ""
"Project-Id-Version: Chinese (Simplified) (Godot Engine)\n"
"POT-Creation-Date: 2018-01-20 12:15+0200\n"
-"PO-Revision-Date: 2019-12-30 17:25+0000\n"
+"PO-Revision-Date: 2020-01-12 13:26+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"
@@ -72,7 +72,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 3.10\n"
+"X-Generator: Weblate 3.10.1\n"
#: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp
#: modules/visual_script/visual_script_builtin_funcs.cpp
@@ -471,7 +471,7 @@ msgstr "无法在没有root的情况下新建轨é“"
#: editor/animation_track_editor.cpp
msgid "Invalid track for Bezier (no suitable sub-properties)"
-msgstr ""
+msgstr "无效的è´å¡žå°”轨é“(没有åˆé€‚çš„å­å±žæ€§ï¼‰"
#: editor/animation_track_editor.cpp
msgid "Add Bezier Track"
@@ -804,7 +804,7 @@ msgstr "必须指定目标节点的方法。"
msgid ""
"Target method not found. Specify a valid method or attach a script to the "
"target node."
-msgstr "找ä¸åˆ°ç›®æ ‡æ–¹æ³•ï¼ 请指定一个有效的方法或者把脚本附加到目标节点。"
+msgstr "找ä¸åˆ°ç›®æ ‡æ–¹æ³•ã€‚请指定一个有效的方法或者把脚本附加到目标节点。"
#: editor/connections_dialog.cpp
msgid "Connect to Node:"
@@ -816,11 +816,11 @@ msgstr "连接到脚本:"
#: editor/connections_dialog.cpp
msgid "From Signal:"
-msgstr "ä¿¡å·æº:"
+msgstr "æ¥è‡ªä¿¡å·ï¼š"
#: editor/connections_dialog.cpp
msgid "Scene does not contain any script."
-msgstr "节点ä¸åŒ…å«è„šæœ¬ã€‚"
+msgstr "场景ä¸åŒ…å«è„šæœ¬ã€‚"
#: editor/connections_dialog.cpp editor/editor_autoload_settings.cpp
#: editor/groups_editor.cpp editor/plugins/item_list_editor_plugin.cpp
@@ -853,11 +853,11 @@ msgstr "接收方法:"
#: editor/connections_dialog.cpp
msgid "Advanced"
-msgstr "高级选项"
+msgstr "高级"
#: editor/connections_dialog.cpp
msgid "Deferred"
-msgstr "延时"
+msgstr "延迟"
#: editor/connections_dialog.cpp
msgid ""
@@ -870,7 +870,7 @@ msgstr "å•æ¬¡"
#: editor/connections_dialog.cpp
msgid "Disconnects the signal after its first emission."
-msgstr "ä¿¡å·è§¦å‘åŽè‡ªåŠ¨å–消连接。"
+msgstr "ä¿¡å·é¦–次触å‘åŽè‡ªåŠ¨æ–­å¼€è¿žæŽ¥ã€‚"
#: editor/connections_dialog.cpp
msgid "Cannot connect signal"
@@ -901,15 +901,15 @@ msgstr "ä¿¡å·ï¼š"
#: editor/connections_dialog.cpp
msgid "Connect '%s' to '%s'"
-msgstr "连接'%s'到'%s'"
+msgstr "连接“%sâ€åˆ°â€œ%sâ€"
#: editor/connections_dialog.cpp
msgid "Disconnect '%s' from '%s'"
-msgstr "å–消'%s'的连接'%s'"
+msgstr "将“%sâ€ä»Žâ€œ%sâ€æ–­å¼€"
#: editor/connections_dialog.cpp
msgid "Disconnect all from signal: '%s'"
-msgstr "å–消广播 '%s' 的所有连接"
+msgstr "断开所有与信å·â€œ%sâ€çš„连接"
#: editor/connections_dialog.cpp
msgid "Connect..."
@@ -930,7 +930,7 @@ msgstr "编辑连接:"
#: editor/connections_dialog.cpp
msgid "Are you sure you want to remove all connections from the \"%s\" signal?"
-msgstr "你确定è¦ä»Žä¿¡å· “%s†中移除所有连接å—?"
+msgstr "你确定è¦ä»Žä¿¡å·â€œ%sâ€ä¸­ç§»é™¤æ‰€æœ‰è¿žæŽ¥å—?"
#: editor/connections_dialog.cpp editor/editor_help.cpp editor/node_dock.cpp
msgid "Signals"
@@ -942,7 +942,7 @@ msgstr "你确定è¦ä»Žè¯¥å¹¿æ’­ä¿¡å·ä¸­ç§»é™¤æ‰€æœ‰è¿žæŽ¥å—?"
#: editor/connections_dialog.cpp
msgid "Disconnect All"
-msgstr "å–消所有广播信å·è¿žæŽ¥"
+msgstr "断开全部"
#: editor/connections_dialog.cpp
msgid "Edit..."
@@ -950,7 +950,7 @@ msgstr "编辑..."
#: editor/connections_dialog.cpp
msgid "Go To Method"
-msgstr "定ä½åˆ°æ–¹æ³•"
+msgstr "跳转到方法"
#: editor/create_dialog.cpp
msgid "Change %s Type"
@@ -999,21 +999,23 @@ msgstr "æœç´¢æ›¿æ¢:"
#: editor/dependency_editor.cpp
msgid "Dependencies For:"
-msgstr "ä¾èµ–项:"
+msgstr "ä¾èµ–项:"
#: editor/dependency_editor.cpp
msgid ""
"Scene '%s' is currently being edited.\n"
"Changes will only take effect when reloaded."
-msgstr "场景 '%s' 已被修改,é‡æ–°åŠ è½½åŽç”Ÿæ•ˆã€‚"
+msgstr ""
+"场景“%sâ€æ­£è¢«ä¿®æ”¹ã€‚\n"
+"修改åªæœ‰åœ¨é‡æ–°åŠ è½½åŽæ‰èƒ½ç”Ÿæ•ˆã€‚"
#: editor/dependency_editor.cpp
msgid ""
"Resource '%s' is in use.\n"
"Changes will only take effect when reloaded."
msgstr ""
-"资æº'%s'正在使用中。\n"
-"修改将åªåœ¨é‡æ–°åŠ è½½åŽç”Ÿæ•ˆã€‚"
+"资æºâ€œ%sâ€æ­£åœ¨ä½¿ç”¨ä¸­ã€‚\n"
+"修改åªæœ‰åœ¨é‡æ–°åŠ è½½åŽæ‰èƒ½ç”Ÿæ•ˆã€‚"
#: editor/dependency_editor.cpp
#: modules/gdnative/gdnative_library_editor_plugin.cpp
@@ -1035,7 +1037,7 @@ msgstr "ä¾èµ–:"
#: editor/dependency_editor.cpp
msgid "Fix Broken"
-msgstr "ä¿®å¤ä¾èµ–"
+msgstr "ä¿®å¤"
#: editor/dependency_editor.cpp
msgid "Dependency Editor"
@@ -1057,30 +1059,32 @@ msgstr "打开"
#: editor/dependency_editor.cpp
msgid "Owners Of:"
-msgstr "拥有者:"
+msgstr "拥有者:"
#: editor/dependency_editor.cpp
msgid "Remove selected files from the project? (Can't be restored)"
-msgstr "确定从项目中删除选定文件?(此æ“作无法撤销)"
+msgstr "是å¦ä»Žé¡¹ç›®ä¸­åˆ é™¤é€‰å®šæ–‡ä»¶ï¼Ÿï¼ˆæ— æ³•æ¢å¤ï¼‰"
#: 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)"
-msgstr "è¦åˆ é™¤çš„文件被其他资æºæ‰€ä¾èµ–,ä»ç„¶è¦åˆ é™¤å—?(无法撤销)"
+msgstr ""
+"è¦åˆ é™¤çš„文件被其他资æºæ‰€ä¾èµ–。\n"
+"ä»ç„¶è¦åˆ é™¤å—?(无法撤销)"
#: editor/dependency_editor.cpp
msgid "Cannot remove:"
-msgstr "无法移除:"
+msgstr "无法移除:"
#: editor/dependency_editor.cpp
msgid "Error loading:"
-msgstr "加载出错:"
+msgstr "加载出错:"
#: editor/dependency_editor.cpp
msgid "Load failed due to missing dependencies:"
-msgstr "由于缺少ä¾èµ–项, 加载失败:"
+msgstr "由于缺少ä¾èµ–项,加载失败:"
#: editor/dependency_editor.cpp editor/editor_node.cpp
msgid "Open Anyway"
@@ -1108,7 +1112,7 @@ msgstr "显示ä¾èµ–"
#: editor/dependency_editor.cpp
msgid "Orphan Resource Explorer"
-msgstr "查看孤立资æº"
+msgstr "孤立资æºæµè§ˆå™¨"
#: editor/dependency_editor.cpp editor/editor_audio_buses.cpp
#: editor/editor_file_dialog.cpp editor/editor_node.cpp
@@ -1120,15 +1124,15 @@ msgstr "删除"
#: editor/dependency_editor.cpp
msgid "Owns"
-msgstr "拥有对象"
+msgstr "拥有"
#: editor/dependency_editor.cpp
msgid "Resources Without Explicit Ownership:"
-msgstr "没有指定所属关系的资æº:"
+msgstr "没有显å¼ä»Žå±žå…³ç³»çš„资æºï¼š"
#: editor/dictionary_property_edit.cpp
msgid "Change Dictionary Key"
-msgstr "修改关键字"
+msgstr "修改字典的键"
#: editor/dictionary_property_edit.cpp
msgid "Change Dictionary Value"
@@ -1225,10 +1229,24 @@ msgid "Error opening package file, not in ZIP format."
msgstr "打开压缩文件时出错,éžzipæ ¼å¼ã€‚"
#: editor/editor_asset_installer.cpp
+#, fuzzy
+msgid "%s (Already Exists)"
+msgstr "å·²ç»å­˜åœ¨"
+
+#: editor/editor_asset_installer.cpp
msgid "Uncompressing Assets"
msgstr "正在解压素æ"
#: editor/editor_asset_installer.cpp editor/project_manager.cpp
+msgid "The following files failed extraction from package:"
+msgstr "以下文件无法从包中æå–:"
+
+#: editor/editor_asset_installer.cpp
+#, fuzzy
+msgid "And %s more files."
+msgstr "其它 %d 个文件"
+
+#: editor/editor_asset_installer.cpp editor/project_manager.cpp
msgid "Package installed successfully!"
msgstr "软件包安装æˆåŠŸï¼"
@@ -1237,6 +1255,11 @@ msgstr "软件包安装æˆåŠŸï¼"
msgid "Success!"
msgstr "æˆåŠŸï¼"
+#: editor/editor_asset_installer.cpp
+#, fuzzy
+msgid "Package Contents:"
+msgstr "内容:"
+
#: editor/editor_asset_installer.cpp editor/editor_node.cpp
msgid "Install"
msgstr "安装"
@@ -1364,7 +1387,7 @@ msgstr "打开音频总线布局"
#: editor/editor_audio_buses.cpp
msgid "There is no '%s' file."
-msgstr "文件 '%s' ä¸å­˜åœ¨ã€‚"
+msgstr "文件“%sâ€ä¸å­˜åœ¨ã€‚"
#: editor/editor_audio_buses.cpp editor/plugins/canvas_item_editor_plugin.cpp
msgid "Layout"
@@ -1375,6 +1398,11 @@ msgid "Invalid file, not an audio bus layout."
msgstr "无效文件,ä¸æ˜¯éŸ³é¢‘总线布局。"
#: editor/editor_audio_buses.cpp
+#, fuzzy
+msgid "Error saving file: %s"
+msgstr "ä¿å­˜æ–‡ä»¶æ—¶å‡ºé”™ï¼"
+
+#: editor/editor_audio_buses.cpp
msgid "Add Bus"
msgstr "添加总线"
@@ -1410,7 +1438,7 @@ msgstr "加载默认总线布局。"
#: editor/editor_audio_buses.cpp
msgid "Create a new Bus Layout."
-msgstr "创建一个新的总线布局。"
+msgstr "创建新的总线布局。"
#: editor/editor_autoload_settings.cpp
msgid "Invalid name."
@@ -1466,7 +1494,7 @@ msgstr "é‡æŽ’åºAutoload"
#: editor/editor_autoload_settings.cpp editor/script_create_dialog.cpp
msgid "Invalid path."
-msgstr "路径éžæ³•ã€‚"
+msgstr "路径无效。"
#: editor/editor_autoload_settings.cpp editor/script_create_dialog.cpp
msgid "File does not exist."
@@ -1485,11 +1513,11 @@ msgstr "添加自动加载"
#: editor/plugins/animation_tree_editor_plugin.cpp
#: editor/script_create_dialog.cpp scene/gui/file_dialog.cpp
msgid "Path:"
-msgstr "路径:"
+msgstr "路径:"
#: editor/editor_autoload_settings.cpp
msgid "Node Name:"
-msgstr "节点å称:"
+msgstr "节点å称:"
#: editor/editor_autoload_settings.cpp editor/editor_help_search.cpp
#: editor/editor_profiler.cpp editor/project_manager.cpp
@@ -1540,7 +1568,7 @@ msgstr "新建文件夹"
#: 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 "å称:"
+msgstr "å称:"
#: editor/editor_dir_dialog.cpp editor/editor_file_dialog.cpp
#: editor/filesystem_dock.cpp scene/gui/file_dialog.cpp
@@ -1553,7 +1581,7 @@ msgstr "选择"
#: editor/editor_export.cpp
msgid "Storing File:"
-msgstr "文件排åº:"
+msgstr "ä¿å­˜æ–‡ä»¶ï¼š"
#: editor/editor_export.cpp
msgid "No export template found at the expected path:"
@@ -1582,24 +1610,24 @@ msgid ""
"Enable 'Import Etc' in Project Settings, or disable 'Driver Fallback "
"Enabled'."
msgstr ""
-"目标平å°éœ€è¦'ETC'纹ç†åŽ‹ç¼©ï¼Œä»¥ä¾¿é©±åŠ¨ç¨‹åºå›žé€€åˆ°GLES2。\n"
+"目标平å°éœ€è¦â€œETCâ€çº¹ç†åŽ‹ç¼©ï¼Œä»¥ä¾¿é©±åŠ¨ç¨‹åºå›žé€€åˆ°GLES2。\n"
"在项目设置中å¯ç”¨â€œå¯¼å…¥Etcâ€ï¼Œæˆ–ç¦ç”¨â€œå¯ç”¨é©±åŠ¨ç¨‹åºå›žé€€â€ã€‚"
#: 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 "找ä¸åˆ°è‡ªå®šä¹‰è°ƒè¯•åŒ…。"
+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
msgid "Custom release template not found."
-msgstr "找ä¸åˆ°è‡ªå®šä¹‰å‘布包。"
+msgstr "找ä¸åˆ°è‡ªå®šä¹‰å‘布模æ¿ã€‚"
#: editor/editor_export.cpp platform/javascript/export/export.cpp
msgid "Template file not found:"
-msgstr "找ä¸åˆ°æ¨¡æ¿æ–‡ä»¶:"
+msgstr "找ä¸åˆ°æ¨¡æ¿æ–‡ä»¶ï¼š"
#: editor/editor_export.cpp
msgid "On 32-bit exports the embedded PCK cannot be bigger than 4 GiB."
@@ -1635,11 +1663,11 @@ msgstr "文件系统和导入é¢æ¿"
#: editor/editor_feature_profile.cpp
msgid "Erase profile '%s'? (no undo)"
-msgstr "删除é…置文件 '%s'? (无法撤销)"
+msgstr "是å¦åˆ é™¤é…置文件“%sâ€ï¼Ÿï¼ˆæ— æ³•æ’¤é”€ï¼‰"
#: editor/editor_feature_profile.cpp
msgid "Profile must be a valid filename and must not contain '.'"
-msgstr "é…置文件必须是有效的文件å,并且ä¸èƒ½åŒ…å« '.'"
+msgstr "é…置文件必须是有效的文件å,并且ä¸èƒ½åŒ…å«â€œ.â€"
#: editor/editor_feature_profile.cpp
msgid "Profile with this name already exists."
@@ -1679,17 +1707,17 @@ msgstr "å¯ç”¨çš„类:"
#: editor/editor_feature_profile.cpp
msgid "File '%s' format is invalid, import aborted."
-msgstr "文件 '%s' æ ¼å¼æ— æ•ˆï¼Œå¯¼å…¥ä¸­æ­¢ã€‚"
+msgstr "文件“%sâ€çš„æ ¼å¼æ— æ•ˆï¼Œå¯¼å…¥ä¸­æ­¢ã€‚"
#: editor/editor_feature_profile.cpp
msgid ""
"Profile '%s' already exists. Remove it first before importing, import "
"aborted."
-msgstr "é…置文件 '%s' 已存在。在导入之å‰å…ˆåˆ é™¤å®ƒï¼Œå¯¼å…¥å·²ä¸­æ­¢ã€‚"
+msgstr "é…置文件“%sâ€å·²å­˜åœ¨ã€‚在导入之å‰å…ˆåˆ é™¤å®ƒï¼Œå¯¼å…¥å·²ä¸­æ­¢ã€‚"
#: editor/editor_feature_profile.cpp
msgid "Error saving profile to path: '%s'."
-msgstr "å°†é…置文件ä¿å­˜åˆ°è·¯å¾„时出错: '%s'。"
+msgstr "å°†é…置文件ä¿å­˜åˆ°è·¯å¾„“%sâ€æ—¶å‡ºé”™ã€‚"
#: editor/editor_feature_profile.cpp
msgid "Unset"
@@ -1756,7 +1784,7 @@ msgstr "选择当å‰æ–‡ä»¶å¤¹"
#: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp
msgid "File Exists, Overwrite?"
-msgstr "文件已存在,确定è¦è¦†ç›–它å—?"
+msgstr "文件已存在,是å¦è¦†ç›–?"
#: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp
msgid "Select This Folder"
@@ -1798,7 +1826,7 @@ msgstr "打开å•ä¸ªæ–‡ä»¶"
#: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp
msgid "Open File(s)"
-msgstr "打开一个或多个文件"
+msgstr "打开文件"
#: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp
msgid "Open a Directory"
@@ -2015,9 +2043,8 @@ msgid "Case Sensitive"
msgstr "区分大å°å†™"
#: editor/editor_help_search.cpp
-#, fuzzy
msgid "Show Hierarchy"
-msgstr "显示辅助信æ¯"
+msgstr "显示层级结构"
#: editor/editor_help_search.cpp
msgid "Display All"
@@ -2056,7 +2083,6 @@ msgid "Class"
msgstr "ç±»"
#: editor/editor_help_search.cpp
-#, fuzzy
msgid "Method"
msgstr "方法"
@@ -2069,12 +2095,10 @@ msgid "Constant"
msgstr "常é‡"
#: editor/editor_help_search.cpp
-#, fuzzy
msgid "Property"
-msgstr "属性:"
+msgstr "属性"
#: editor/editor_help_search.cpp
-#, fuzzy
msgid "Theme Property"
msgstr "主题属性"
@@ -2084,19 +2108,19 @@ msgstr "属性:"
#: editor/editor_inspector.cpp
msgid "Set"
-msgstr "Set"
+msgstr "设置"
#: editor/editor_inspector.cpp
msgid "Set Multiple:"
-msgstr "设置乘数:"
+msgstr "批é‡è®¾ç½®ï¼š"
#: editor/editor_log.cpp
msgid "Output:"
-msgstr "日志:"
+msgstr "输出:"
#: editor/editor_log.cpp editor/plugins/tile_map_editor_plugin.cpp
msgid "Copy Selection"
-msgstr "å¤åˆ¶é€‰æ‹©"
+msgstr "å¤åˆ¶æ‰€é€‰é¡¹"
#: editor/editor_log.cpp editor/editor_network_profiler.cpp
#: editor/editor_profiler.cpp editor/editor_properties.cpp
@@ -2128,11 +2152,11 @@ msgstr "%s/s"
#: editor/editor_network_profiler.cpp
msgid "Down"
-msgstr "å‘下"
+msgstr "下载"
#: editor/editor_network_profiler.cpp
msgid "Up"
-msgstr "å‘上"
+msgstr "上传"
#: editor/editor_network_profiler.cpp editor/editor_node.cpp
msgid "Node"
@@ -2159,10 +2183,6 @@ msgid "New Window"
msgstr "新建窗å£"
#: editor/editor_node.cpp
-msgid "Project export failed with error code %d."
-msgstr "é¡¹ç›®å¯¼å‡ºå¤±è´¥ï¼Œé”™è¯¯ä»£ç  %d。"
-
-#: editor/editor_node.cpp
msgid "Imported resources can't be saved."
msgstr "导入的资æºæ— æ³•ä¿å­˜ã€‚"
@@ -2187,11 +2207,11 @@ msgstr "资æºå¦å­˜ä¸º..."
#: editor/editor_node.cpp
msgid "Can't open file for writing:"
-msgstr "无法以å¯å†™æ¨¡å¼æ‰“开文件:"
+msgstr "无法以å¯å†™æ¨¡å¼æ‰“开文件:"
#: editor/editor_node.cpp
msgid "Requested file format unknown:"
-msgstr "未知的文件类型请求:"
+msgstr "未知的文件类型请求:"
#: editor/editor_node.cpp
msgid "Error while saving."
@@ -2304,8 +2324,7 @@ msgstr ""
msgid ""
"This resource was imported, so it's not editable. Change its settings in the "
"import panel and then re-import."
-msgstr ""
-"此资æºå·²å¯¼å…¥, 因此无法编辑。在 \"导入\" é¢æ¿ä¸­æ›´æ”¹å…¶è®¾ç½®, 然åŽé‡æ–°å¯¼å…¥ã€‚"
+msgstr "此资æºå·²å¯¼å…¥ï¼Œå› æ­¤æ— æ³•ç¼–辑。在“导入â€é¢æ¿ä¸­æ›´æ”¹è®¾ç½®ï¼Œç„¶åŽé‡æ–°å¯¼å…¥ã€‚"
#: editor/editor_node.cpp
msgid ""
@@ -2475,7 +2494,7 @@ msgstr "é‡æ–°æ‰“开关闭的场景"
#: editor/editor_node.cpp
msgid "Unable to enable addon plugin at: '%s' parsing of config failed."
-msgstr "无法在: \"%s\" 上å¯ç”¨åŠ è½½é¡¹æ’件, é…置解æžå¤±è´¥ã€‚"
+msgstr "无法在“%sâ€ä¸Šå¯ç”¨åŠ è½½é¡¹æ’件:é…置解æžå¤±è´¥ã€‚"
#: editor/editor_node.cpp
msgid "Unable to find script field for addon plugin at: 'res://addons/%s'."
@@ -2483,22 +2502,22 @@ msgstr "无法在“res://addons/%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’ 脚本看上去似乎有代ç é”™è¯¯ï¼Œè¯·æ£€æŸ¥å…¶è¯­æ³•ã€‚"
+msgstr "无法从路径加载æ’件脚本:“%sâ€è„šæœ¬çœ‹ä¸ŠåŽ»ä¼¼ä¹Žæœ‰ä»£ç é”™è¯¯ï¼Œè¯·æ£€æŸ¥å…¶è¯­æ³•ã€‚"
#: editor/editor_node.cpp
msgid ""
"Unable to load addon script from path: '%s' Base type is not EditorPlugin."
-msgstr "无法从路径加载æ’件脚本: \"%s\" 基类型ä¸æ˜¯ 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\" 脚本ä¸åœ¨å·¥å…·æ¨¡å¼ä¸‹ã€‚"
+msgstr "无法从路径加载æ’件脚本:“%sâ€è„šæœ¬ä¸åœ¨å·¥å…·æ¨¡å¼ä¸‹ã€‚"
#: editor/editor_node.cpp
msgid ""
@@ -2518,7 +2537,7 @@ msgstr ""
#: editor/editor_node.cpp
msgid "Scene '%s' has broken dependencies:"
-msgstr "场景'%s'çš„ä¾èµ–已被破å:"
+msgstr "场景“%sâ€çš„ä¾èµ–已被破å:"
#: editor/editor_node.cpp
msgid "Clear Recent Scenes"
@@ -2530,8 +2549,8 @@ msgid ""
"You can change it later in \"Project Settings\" under the 'application' "
"category."
msgstr ""
-"尚未定义主场景, 现在选择一个�\n"
-"你也å¯ä»¥ç¨åŽåœ¨é¡¹ç›®è®¾ç½®çš„application分类下修改。"
+"尚未定义主场景,是å¦é€‰æ‹©ä¸€ä¸ªï¼Ÿ\n"
+"ä½ å¯ä»¥ç¨åŽåœ¨â€œé¡¹ç›®è®¾ç½®â€çš„“applicationâ€åˆ†ç±»ä¸‹ä¿®æ”¹ã€‚"
#: editor/editor_node.cpp
msgid ""
@@ -2539,8 +2558,8 @@ msgid ""
"You can change it later in \"Project Settings\" under the 'application' "
"category."
msgstr ""
-"所选场景“%sâ€ä¸å­˜åœ¨ï¼Œé€‰æ‹©ä¸€ä¸ªæœ‰æ•ˆçš„场景?\n"
-"请在项目设置的application(应用程åºï¼‰åˆ†ç±»ä¸‹è®¾ç½®é€‰æ‹©ä¸»åœºæ™¯ã€‚"
+"所选场景“%sâ€ä¸å­˜åœ¨ï¼Œæ˜¯å¦é€‰æ‹©æœ‰æ•ˆçš„场景?\n"
+"请在“项目设置â€çš„“applicationâ€åˆ†ç±»ä¸‹è®¾ç½®é€‰æ‹©ä¸»åœºæ™¯ã€‚"
#: editor/editor_node.cpp
msgid ""
@@ -2587,7 +2606,7 @@ msgstr "关闭其他标签页"
#: editor/editor_node.cpp
msgid "Close Tabs to the Right"
-msgstr "关闭å³ä¾§"
+msgstr "关闭å³ä¾§æ ‡ç­¾é¡µ"
#: editor/editor_node.cpp
msgid "Close All Tabs"
@@ -3038,10 +3057,6 @@ msgstr "从ZIP文件中导入模æ¿"
msgid "Template Package"
msgstr "模æ¿åŒ…"
-#: editor/editor_node.cpp editor/project_export.cpp
-msgid "Export Project"
-msgstr "导出项目"
-
#: editor/editor_node.cpp
msgid "Export Library"
msgstr "导出库"
@@ -3051,10 +3066,6 @@ msgid "Merge With Existing"
msgstr "与现有åˆå¹¶"
#: editor/editor_node.cpp
-msgid "Password:"
-msgstr "密ç :"
-
-#: editor/editor_node.cpp
msgid "Open & Run a Script"
msgstr "打开并è¿è¡Œè„šæœ¬"
@@ -3412,13 +3423,12 @@ msgid "Importing:"
msgstr "导入:"
#: editor/export_template_manager.cpp
-#, fuzzy
msgid "Error getting the list of mirrors."
-msgstr "创建包(PCK)ç­¾å对象出错。"
+msgstr "获å–é•œåƒåˆ—表时出错。"
#: editor/export_template_manager.cpp
msgid "Error parsing JSON of mirror list. Please report this issue!"
-msgstr ""
+msgstr "解æžé•œåƒåˆ—表JSON时出错。请æ交此问题ï¼"
#: editor/export_template_manager.cpp
msgid ""
@@ -3491,7 +3501,7 @@ msgstr "无法解æž"
#: editor/export_template_manager.cpp
#: editor/plugins/asset_library_editor_plugin.cpp
msgid "Connecting..."
-msgstr "连接中..."
+msgstr "正在连接..."
#: editor/export_template_manager.cpp
msgid "Can't Connect"
@@ -3504,7 +3514,7 @@ msgstr "已连接"
#: editor/export_template_manager.cpp
#: editor/plugins/asset_library_editor_plugin.cpp
msgid "Requesting..."
-msgstr "正在请求。。"
+msgstr "正在请求..."
#: editor/export_template_manager.cpp
msgid "Downloading"
@@ -3938,7 +3948,7 @@ msgstr " 文件"
#: editor/import_dock.cpp
msgid "Import As:"
-msgstr "导入为:"
+msgstr "导入为:"
#: editor/import_dock.cpp
msgid "Preset"
@@ -4585,9 +4595,8 @@ msgid "Move Node"
msgstr "移动节点"
#: editor/plugins/animation_state_machine_editor.cpp
-#, fuzzy
msgid "Transition exists!"
-msgstr "过渡"
+msgstr "过渡已存在ï¼"
#: editor/plugins/animation_state_machine_editor.cpp
msgid "Add Transition"
@@ -5498,11 +5507,11 @@ msgstr "显示分组和é”定图标"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Center Selection"
-msgstr "居中显示选中节点"
+msgstr "居中显示所选项"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Frame Selection"
-msgstr "最大化显示选中节点"
+msgstr "完整显示所选项"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Preview Canvas Scale"
@@ -5616,7 +5625,7 @@ msgstr "设置处ç†ç¨‹åº"
#: editor/plugins/cpu_particles_2d_editor_plugin.cpp
#: editor/plugins/particles_2d_editor_plugin.cpp
msgid "Load Emission Mask"
-msgstr "加载Emission Mask(å‘å°„å±è”½ï¼‰"
+msgstr "加载å‘å°„é®ç½©"
#: editor/plugins/cpu_particles_2d_editor_plugin.cpp
#: editor/plugins/cpu_particles_editor_plugin.cpp
@@ -5628,7 +5637,7 @@ msgstr "é‡æ–°å¯åŠ¨"
#: editor/plugins/cpu_particles_2d_editor_plugin.cpp
#: editor/plugins/particles_2d_editor_plugin.cpp
msgid "Clear Emission Mask"
-msgstr "清除å‘å°„å±è”½"
+msgstr "清除å‘å°„é®ç½©"
#: editor/plugins/cpu_particles_2d_editor_plugin.cpp
#: editor/plugins/particles_2d_editor_plugin.cpp
@@ -5648,6 +5657,23 @@ msgstr "å‘å°„é®ç½©"
#: editor/plugins/cpu_particles_2d_editor_plugin.cpp
#: editor/plugins/particles_2d_editor_plugin.cpp
+#, fuzzy
+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
+#, fuzzy
+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 "从åƒç´ æ•èŽ·"
@@ -5873,18 +5899,19 @@ msgstr "轮廓大å°ï¼š"
#: editor/plugins/mesh_instance_editor_plugin.cpp
msgid "UV Channel Debug"
-msgstr ""
+msgstr "调试UV通é“"
#: editor/plugins/mesh_library_editor_plugin.cpp
msgid "Remove item %d?"
msgstr "确定è¦ç§»é™¤é¡¹ç›®%då—?"
#: editor/plugins/mesh_library_editor_plugin.cpp
-#, fuzzy
msgid ""
"Update from existing scene?:\n"
"%s"
-msgstr "从场景中更新"
+msgstr ""
+"是å¦ä»Žå·²æœ‰åœºæ™¯ä¸­æ›´æ–°ï¼Ÿï¼š\n"
+"%s"
#: editor/plugins/mesh_library_editor_plugin.cpp
msgid "Mesh Library"
@@ -6297,7 +6324,7 @@ msgstr "点"
#: editor/plugins/polygon_2d_editor_plugin.cpp
msgid "Polygons"
-msgstr "多边形-"
+msgstr "多边形"
#: editor/plugins/polygon_2d_editor_plugin.cpp
msgid "Bones"
@@ -6850,7 +6877,7 @@ msgstr "切æ¢æ³¨é‡Š"
#: editor/plugins/script_text_editor.cpp
msgid "Fold/Unfold Line"
-msgstr "切æ¢å è¡Œ"
+msgstr "折å /展开当å‰è¡Œ"
#: editor/plugins/script_text_editor.cpp
msgid "Fold All Lines"
@@ -7071,7 +7098,7 @@ msgstr "顶点"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Top View."
-msgstr "俯视图。"
+msgstr "顶视图。"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Bottom View."
@@ -7143,7 +7170,7 @@ msgstr "显示线框"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Display Overdraw"
-msgstr "显示过度绘制"
+msgstr "显示é‡å¤ç»˜åˆ¶"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Display Unshaded"
@@ -7151,7 +7178,7 @@ msgstr "显示无阴影"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "View Environment"
-msgstr "视图环境"
+msgstr "查看环境"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "View Gizmos"
@@ -7179,7 +7206,7 @@ msgstr "å¯ç”¨å¤šæ™®å‹’效应"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Cinematic Preview"
-msgstr "影片预览"
+msgstr "效果预览"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Freelook Left"
@@ -7235,7 +7262,7 @@ msgstr "将节点å¸é™„至地é¢"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Couldn't find a solid floor to snap the selection to."
-msgstr "找ä¸åˆ°ä¸€ä¸ªåšå®žçš„地æ¿æ¥å¿«é€Ÿé€‰æ‹©ã€‚"
+msgstr "找ä¸åˆ°å¯å¸é™„çš„åšå®žåœ°æ¿ã€‚"
#: editor/plugins/spatial_editor_plugin.cpp
msgid ""
@@ -7257,11 +7284,11 @@ msgstr "使用å¸é™„"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Bottom View"
-msgstr "底部视图"
+msgstr "底视图"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Top View"
-msgstr "俯视图"
+msgstr "顶视图"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Rear View"
@@ -7371,7 +7398,7 @@ msgstr "缩放å¸é™„(%):"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Viewport Settings"
-msgstr "Viewport设置"
+msgstr "视å£è®¾ç½®"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Perspective FOV (deg.):"
@@ -7419,38 +7446,35 @@ msgstr "æ— å控制器"
#: editor/plugins/sprite_editor_plugin.cpp
msgid "Create Mesh2D"
-msgstr "创建 2D 网格"
+msgstr "创建Mesh2D"
#: editor/plugins/sprite_editor_plugin.cpp
-#, fuzzy
msgid "Mesh2D Preview"
-msgstr "创建网格预览"
+msgstr "Mesh2D预览"
#: editor/plugins/sprite_editor_plugin.cpp
msgid "Create Polygon2D"
-msgstr "创建2D多边形"
+msgstr "创建Polygon 2D"
#: editor/plugins/sprite_editor_plugin.cpp
msgid "Polygon2D Preview"
-msgstr ""
+msgstr "Polygon2D预览"
#: editor/plugins/sprite_editor_plugin.cpp
msgid "Create CollisionPolygon2D"
-msgstr "创建2D碰撞多边形"
+msgstr "创建CollisionPolygon2D"
#: editor/plugins/sprite_editor_plugin.cpp
-#, fuzzy
msgid "CollisionPolygon2D Preview"
-msgstr "创建2D碰撞多边形"
+msgstr "CollisionPolygon2D预览"
#: editor/plugins/sprite_editor_plugin.cpp
msgid "Create LightOccluder2D"
-msgstr "添加2Dé®å…‰å¤šè¾¹å½¢"
+msgstr "创建LightOccluder2D"
#: editor/plugins/sprite_editor_plugin.cpp
-#, fuzzy
msgid "LightOccluder2D Preview"
-msgstr "添加2Dé®å…‰å¤šè¾¹å½¢"
+msgstr "LightOccluder2D预览"
#: editor/plugins/sprite_editor_plugin.cpp
msgid "Sprite is empty!"
@@ -7466,7 +7490,7 @@ msgstr "无效的几何体,无法使用网格替æ¢ã€‚"
#: editor/plugins/sprite_editor_plugin.cpp
msgid "Convert to Mesh2D"
-msgstr "转æ¢ä¸º 2D 网格"
+msgstr "转æ¢ä¸ºMesh2D"
#: editor/plugins/sprite_editor_plugin.cpp
msgid "Invalid geometry, can't create polygon."
@@ -7474,7 +7498,7 @@ msgstr "无效的几何体,无法创建多边形。"
#: editor/plugins/sprite_editor_plugin.cpp
msgid "Convert to Polygon2D"
-msgstr "转æ¢ä¸ºå¤šè¾¹å½¢"
+msgstr "转æ¢ä¸ºPolygon2D"
#: editor/plugins/sprite_editor_plugin.cpp
msgid "Invalid geometry, can't create collision polygon."
@@ -7482,7 +7506,7 @@ msgstr "无效的几何体,无法创建多边形碰撞体。"
#: editor/plugins/sprite_editor_plugin.cpp
msgid "Create CollisionPolygon2D Sibling"
-msgstr "创建2D碰撞多边形æˆå‘˜"
+msgstr "创建CollisionPolygon2D兄弟节点"
#: editor/plugins/sprite_editor_plugin.cpp
msgid "Invalid geometry, can't create light occluder."
@@ -7490,7 +7514,7 @@ msgstr "无效的几何体,无法创建é®å…‰ä½“。"
#: editor/plugins/sprite_editor_plugin.cpp
msgid "Create LightOccluder2D Sibling"
-msgstr "创建2Dé®å…‰å¤šè¾¹å½¢æˆå‘˜"
+msgstr "创建LightOccluder2D兄弟节点"
#: editor/plugins/sprite_editor_plugin.cpp
msgid "Sprite"
@@ -7529,13 +7553,12 @@ msgid "Add Frame"
msgstr "添加帧"
#: editor/plugins/sprite_frames_editor_plugin.cpp
-#, fuzzy
msgid "Unable to load images"
-msgstr "无法加载图片:"
+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!"
@@ -7829,7 +7852,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"
@@ -7838,7 +7861,7 @@ msgstr "ä¿®å¤æ— æ•ˆçš„图å—"
#: editor/plugins/tile_map_editor_plugin.cpp
#: modules/gridmap/grid_map_editor_plugin.cpp
msgid "Cut Selection"
-msgstr "切割选择"
+msgstr "剪切选中项"
#: editor/plugins/tile_map_editor_plugin.cpp
msgid "Paint TileMap"
@@ -7846,7 +7869,7 @@ msgstr "绘制图å—地图"
#: editor/plugins/tile_map_editor_plugin.cpp
msgid "Line Draw"
-msgstr "线性绘制"
+msgstr "绘制直线"
#: editor/plugins/tile_map_editor_plugin.cpp
msgid "Rectangle Paint"
@@ -8215,14 +8238,12 @@ msgid "Edit Tile Z Index"
msgstr "ç¼–è¾‘å›¾å— Z åæ ‡"
#: editor/plugins/tile_set_editor_plugin.cpp
-#, fuzzy
msgid "Make Convex"
-msgstr "使多边形凸起"
+msgstr "转为凸多边形"
#: editor/plugins/tile_set_editor_plugin.cpp
-#, fuzzy
msgid "Make Concave"
-msgstr "使多边形塌陷"
+msgstr "转为凹多边形"
#: editor/plugins/tile_set_editor_plugin.cpp
msgid "Create Collision Polygon"
@@ -9179,7 +9200,7 @@ msgstr "添加已有补ä¸..."
#: editor/project_export.cpp
msgid "Delete patch '%s' from list?"
-msgstr "从列表中删除补ä¸''%s'?"
+msgstr "是å¦ä»Žåˆ—表中删除补ä¸â€œ%sâ€ï¼Ÿ"
#: editor/project_export.cpp
msgid "Delete preset '%s'?"
@@ -9335,6 +9356,10 @@ msgid "Export PCK/Zip"
msgstr "导出 PCK/ZIP"
#: editor/project_export.cpp
+msgid "Export Project"
+msgstr "导出项目"
+
+#: editor/project_export.cpp
msgid "Export mode?"
msgstr "导出模å¼ï¼Ÿ"
@@ -9392,7 +9417,7 @@ msgstr "已导入的项目"
#: editor/project_manager.cpp
msgid "Invalid Project Name."
-msgstr "无效项目å称。"
+msgstr "项目å称无效。"
#: editor/project_manager.cpp
msgid "Couldn't create folder."
@@ -9426,10 +9451,6 @@ msgid "Couldn't create project.godot in project path."
msgstr "无法在项目路径下创建project.godot文件。"
#: editor/project_manager.cpp
-msgid "The following files failed extraction from package:"
-msgstr "以下文件无法从包中æå–:"
-
-#: editor/project_manager.cpp
msgid "Rename Project"
msgstr "é‡å‘½å项目"
@@ -9459,7 +9480,7 @@ msgstr "安装并编辑"
#: editor/project_manager.cpp
msgid "Project Name:"
-msgstr "项目å称:"
+msgstr "项目å称:"
#: editor/project_manager.cpp
msgid "Project Path:"
@@ -9605,7 +9626,9 @@ msgstr ""
msgid ""
"Remove this project from the list?\n"
"The project folder's contents won't be modified."
-msgstr "从列表中删除该项目? 项目文件夹的内容ä¸ä¼šè¢«ä¿®æ”¹ã€‚"
+msgstr ""
+"是å¦ä»Žåˆ—表中删除该项目?\n"
+"项目文件夹的内容ä¸ä¼šè¢«ä¿®æ”¹ã€‚"
#: editor/project_manager.cpp
msgid ""
@@ -10421,7 +10444,7 @@ msgstr "å¤åˆ¶èŠ‚点路径"
#: editor/scene_tree_dock.cpp
msgid "Delete (No Confirm)"
-msgstr "确认删除"
+msgstr "删除(无确认)"
#: editor/scene_tree_dock.cpp
msgid "Add/Create a New Node."
@@ -10539,7 +10562,7 @@ msgstr "é‡å‘½å节点"
#: editor/scene_tree_editor.cpp
msgid "Scene Tree (Nodes):"
-msgstr "场景树:"
+msgstr "场景树(节点):"
#: editor/scene_tree_editor.cpp
msgid "Node Configuration Warning!"
@@ -10638,6 +10661,11 @@ msgid "Will load an existing script file."
msgstr "将加载现有的脚本文件。"
#: editor/script_create_dialog.cpp
+#, fuzzy
+msgid "Script file already exists."
+msgstr "拆分已存在。"
+
+#: editor/script_create_dialog.cpp
msgid "Class Name:"
msgstr "ç±»å:"
@@ -10743,7 +10771,7 @@ msgstr "监视"
#: editor/script_editor_debugger.cpp
msgid "Pick one or more items from the list to display the graph."
-msgstr "从列表中选å–一个或多个项目以显示图形。"
+msgstr "从列表中选å–一个或多个项目以显示图表。"
#: editor/script_editor_debugger.cpp
msgid "List of Video Memory Usage by Resource:"
@@ -11086,9 +11114,8 @@ msgid "Cursor Clear Rotation"
msgstr "光标清除旋转"
#: modules/gridmap/grid_map_editor_plugin.cpp
-#, fuzzy
msgid "Paste Selects"
-msgstr "擦除选中"
+msgstr "粘贴选中项"
#: modules/gridmap/grid_map_editor_plugin.cpp
msgid "Clear Selection"
@@ -12225,7 +12252,15 @@ msgid "This node has been deprecated. Use AnimationTree instead."
msgstr "这个节点已被弃用。请使用Animation Tree代替。"
#: scene/gui/color_picker.cpp
-msgid "Pick a color from the screen."
+msgid ""
+"Color: #%s\n"
+"LMB: Set color\n"
+"RMB: Remove preset"
+msgstr ""
+
+#: scene/gui/color_picker.cpp
+#, fuzzy
+msgid "Pick a color from the editor window."
msgstr "从å±å¹•ä¸­é€‰æ‹©ä¸€ç§é¢œè‰²ã€‚"
#: scene/gui/color_picker.cpp
@@ -12340,6 +12375,12 @@ msgstr "å˜é‡åªèƒ½åœ¨é¡¶ç‚¹å‡½æ•°ä¸­æŒ‡å®šã€‚"
msgid "Constants cannot be modified."
msgstr "ä¸å…许修改常é‡ã€‚"
+#~ msgid "Project export failed with error code %d."
+#~ msgstr "é¡¹ç›®å¯¼å‡ºå¤±è´¥ï¼Œé”™è¯¯ä»£ç  %d。"
+
+#~ msgid "Password:"
+#~ msgstr "密ç :"
+
#~ msgid "Identifier segments must be of non-zero length."
#~ msgstr "标识符字段ä¸èƒ½ä¸ºç©º."
@@ -12628,9 +12669,6 @@ msgstr "ä¸å…许修改常é‡ã€‚"
#~ msgid "Create folder"
#~ msgstr "新建目录"
-#~ msgid "Already existing"
-#~ msgstr "å·²ç»å­˜åœ¨"
-
#~ msgid "Custom Node"
#~ msgstr "自定义节点"
@@ -12680,9 +12718,6 @@ msgstr "ä¸å…许修改常é‡ã€‚"
#~ msgid "Split can't form an existing edge."
#~ msgstr "ä¸èƒ½ä»Žå·²å­˜åœ¨çš„边上拆分。"
-#~ msgid "Split already exists."
-#~ msgstr "拆分已存在。"
-
#~ msgid "Add Split"
#~ msgstr "添加分裂"
diff --git a/editor/translations/zh_HK.po b/editor/translations/zh_HK.po
index ae22ddc75c..d52249df61 100644
--- a/editor/translations/zh_HK.po
+++ b/editor/translations/zh_HK.po
@@ -1255,10 +1255,24 @@ msgstr ""
#: editor/editor_asset_installer.cpp
#, fuzzy
+msgid "%s (Already Exists)"
+msgstr "AutoLoad '%s'已存在ï¼"
+
+#: editor/editor_asset_installer.cpp
+#, fuzzy
msgid "Uncompressing Assets"
msgstr "導入中:"
#: editor/editor_asset_installer.cpp editor/project_manager.cpp
+msgid "The following files failed extraction from package:"
+msgstr ""
+
+#: editor/editor_asset_installer.cpp
+#, fuzzy
+msgid "And %s more files."
+msgstr "多 %d 檔案"
+
+#: editor/editor_asset_installer.cpp editor/project_manager.cpp
msgid "Package installed successfully!"
msgstr ""
@@ -1267,6 +1281,11 @@ msgstr ""
msgid "Success!"
msgstr "æˆåŠŸï¼"
+#: editor/editor_asset_installer.cpp
+#, fuzzy
+msgid "Package Contents:"
+msgstr "內容:"
+
#: editor/editor_asset_installer.cpp editor/editor_node.cpp
msgid "Install"
msgstr "安è£"
@@ -1418,6 +1437,11 @@ msgid "Invalid file, not an audio bus layout."
msgstr ""
#: editor/editor_audio_buses.cpp
+#, fuzzy
+msgid "Error saving file: %s"
+msgstr "儲存TileSet時出ç¾éŒ¯èª¤ï¼"
+
+#: editor/editor_audio_buses.cpp
msgid "Add Bus"
msgstr ""
@@ -2272,10 +2296,6 @@ msgid "New Window"
msgstr ""
#: editor/editor_node.cpp
-msgid "Project export failed with error code %d."
-msgstr ""
-
-#: editor/editor_node.cpp
msgid "Imported resources can't be saved."
msgstr ""
@@ -3181,10 +3201,6 @@ msgstr "從ZIP檔"
msgid "Template Package"
msgstr "移除é¸é …"
-#: editor/editor_node.cpp editor/project_export.cpp
-msgid "Export Project"
-msgstr ""
-
#: editor/editor_node.cpp
msgid "Export Library"
msgstr ""
@@ -3194,10 +3210,6 @@ msgid "Merge With Existing"
msgstr ""
#: editor/editor_node.cpp
-msgid "Password:"
-msgstr "密碼:"
-
-#: editor/editor_node.cpp
msgid "Open & Run a Script"
msgstr ""
@@ -5967,6 +5979,22 @@ 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
+#, fuzzy
+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 ""
@@ -9807,6 +9835,10 @@ msgid "Export PCK/Zip"
msgstr "匯出"
#: editor/project_export.cpp
+msgid "Export Project"
+msgstr ""
+
+#: editor/project_export.cpp
#, fuzzy
msgid "Export mode?"
msgstr "匯出"
@@ -9903,10 +9935,6 @@ msgid "Couldn't create project.godot in project path."
msgstr ""
#: editor/project_manager.cpp
-msgid "The following files failed extraction from package:"
-msgstr ""
-
-#: editor/project_manager.cpp
#, fuzzy
msgid "Rename Project"
msgstr "專案"
@@ -11142,6 +11170,11 @@ msgstr "下一個腳本"
#: editor/script_create_dialog.cpp
#, fuzzy
+msgid "Script file already exists."
+msgstr "AutoLoad '%s'已存在ï¼"
+
+#: editor/script_create_dialog.cpp
+#, fuzzy
msgid "Class Name:"
msgstr "å稱:"
@@ -12750,7 +12783,14 @@ msgid "This node has been deprecated. Use AnimationTree instead."
msgstr ""
#: scene/gui/color_picker.cpp
-msgid "Pick a color from the screen."
+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
@@ -12857,6 +12897,9 @@ msgstr ""
msgid "Constants cannot be modified."
msgstr ""
+#~ msgid "Password:"
+#~ msgstr "密碼:"
+
#~ msgid "Pause the scene"
#~ msgstr "æš«åœå ´æ™¯"
@@ -13006,10 +13049,6 @@ msgstr ""
#~ msgstr "列:"
#, fuzzy
-#~ msgid "Split already exists."
-#~ msgstr "AutoLoad '%s'已存在ï¼"
-
-#, fuzzy
#~ msgid "Add Split"
#~ msgstr "新增訊號"
diff --git a/editor/translations/zh_TW.po b/editor/translations/zh_TW.po
index d20cad9133..1ca1a64015 100644
--- a/editor/translations/zh_TW.po
+++ b/editor/translations/zh_TW.po
@@ -18,12 +18,13 @@
# leela <53352@protonmail.com>, 2019.
# Kenneth Lo <closer.tw@gmail.com>, 2019.
# SIYU FU <1002492607@qq.com>, 2019.
+# 鄭惟中 <biglionlion06@gmail.com>, 2020.
msgid ""
msgstr ""
"Project-Id-Version: Godot Engine editor\n"
"POT-Creation-Date: \n"
-"PO-Revision-Date: 2019-11-09 22:04+0000\n"
-"Last-Translator: SIYU FU <1002492607@qq.com>\n"
+"PO-Revision-Date: 2020-01-11 03:05+0000\n"
+"Last-Translator: 鄭惟中 <biglionlion06@gmail.com>\n"
"Language-Team: Chinese (Traditional) <https://hosted.weblate.org/projects/"
"godot-engine/godot/zh_Hant/>\n"
"Language: zh_TW\n"
@@ -31,16 +32,16 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=1; plural=0;\n"
-"X-Generator: Weblate 3.10-dev\n"
+"X-Generator: Weblate 3.10.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)."
-msgstr ""
+msgstr "應為一個長度是1(一個字元)的字串"
#: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp
#: modules/mono/glue/gd_glue.cpp
@@ -78,7 +79,7 @@ msgstr "調用“%sâ€æ™‚:"
#: core/ustring.cpp
msgid "B"
-msgstr "ä¹™"
+msgstr "Byte"
#: core/ustring.cpp
msgid "KiB"
@@ -86,7 +87,7 @@ msgstr "基布"
#: core/ustring.cpp
msgid "MiB"
-msgstr "MiBå…¬å¸"
+msgstr "MiB"
#: core/ustring.cpp
msgid "GiB"
@@ -106,7 +107,7 @@ msgstr ""
#: editor/animation_bezier_editor.cpp
msgid "Free"
-msgstr "释放"
+msgstr "釋放"
#: editor/animation_bezier_editor.cpp
msgid "Balanced"
@@ -114,7 +115,7 @@ msgstr "平衡"
#: editor/animation_bezier_editor.cpp
msgid "Mirror"
-msgstr "é•œåƒ"
+msgstr "é¡åƒ"
#: editor/animation_bezier_editor.cpp editor/editor_profiler.cpp
msgid "Time:"
@@ -1254,10 +1255,24 @@ msgid "Error opening package file, not in ZIP format."
msgstr "é–‹å•Ÿå¥—ä»¶æª”æ¡ˆå‡ºéŒ¯ï¼Œéž zip æ ¼å¼ã€‚"
#: editor/editor_asset_installer.cpp
+#, fuzzy
+msgid "%s (Already Exists)"
+msgstr "Autoload「%sã€å·²ç¶“存在!"
+
+#: editor/editor_asset_installer.cpp
msgid "Uncompressing Assets"
msgstr "正在解壓縮素æ"
#: editor/editor_asset_installer.cpp editor/project_manager.cpp
+msgid "The following files failed extraction from package:"
+msgstr "æå–以下檔案失敗:"
+
+#: editor/editor_asset_installer.cpp
+#, fuzzy
+msgid "And %s more files."
+msgstr "還有 %d 個檔案"
+
+#: editor/editor_asset_installer.cpp editor/project_manager.cpp
#, fuzzy
msgid "Package installed successfully!"
msgstr "套件安è£æˆåŠŸ!"
@@ -1267,6 +1282,11 @@ msgstr "套件安è£æˆåŠŸ!"
msgid "Success!"
msgstr "æˆåŠŸ!"
+#: editor/editor_asset_installer.cpp
+#, fuzzy
+msgid "Package Contents:"
+msgstr "內容:"
+
#: editor/editor_asset_installer.cpp editor/editor_node.cpp
msgid "Install"
msgstr "安è£"
@@ -1413,6 +1433,11 @@ msgid "Invalid file, not an audio bus layout."
msgstr "檔案格å¼ä¸æ­£ç¢ºï¼Œä¸æ˜¯ Audio Bus é…置檔。"
#: editor/editor_audio_buses.cpp
+#, fuzzy
+msgid "Error saving file: %s"
+msgstr "儲存資æºéŒ¯èª¤!"
+
+#: editor/editor_audio_buses.cpp
msgid "Add Bus"
msgstr "新增 Bus"
@@ -2273,10 +2298,6 @@ msgid "New Window"
msgstr ""
#: editor/editor_node.cpp
-msgid "Project export failed with error code %d."
-msgstr "專案輸出失敗,錯誤代碼是 %d。"
-
-#: editor/editor_node.cpp
msgid "Imported resources can't be saved."
msgstr "無法ä¿å­˜å°Žå…¥çš„資æºã€‚"
@@ -3174,10 +3195,6 @@ msgstr "導入模æ¿ï¼ˆé€éŽZIP檔案)"
msgid "Template Package"
msgstr "導出範本管ç†å™¨"
-#: editor/editor_node.cpp editor/project_export.cpp
-msgid "Export Project"
-msgstr "輸出專案"
-
#: editor/editor_node.cpp
msgid "Export Library"
msgstr "輸出函å¼åº«"
@@ -3187,10 +3204,6 @@ msgid "Merge With Existing"
msgstr "與ç¾æœ‰å‡½å¼åº«åˆä½µ"
#: editor/editor_node.cpp
-msgid "Password:"
-msgstr "密碼:"
-
-#: editor/editor_node.cpp
msgid "Open & Run a Script"
msgstr "開啟並é‹è¡Œè…³æœ¬"
@@ -5946,6 +5959,23 @@ msgstr ""
#: editor/plugins/cpu_particles_2d_editor_plugin.cpp
#: editor/plugins/particles_2d_editor_plugin.cpp
+#, fuzzy
+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
+#, fuzzy
+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 ""
@@ -9779,6 +9809,10 @@ msgid "Export PCK/Zip"
msgstr "導出 PCK/ZIP"
#: editor/project_export.cpp
+msgid "Export Project"
+msgstr "輸出專案"
+
+#: editor/project_export.cpp
#, fuzzy
msgid "Export mode?"
msgstr "導出模å¼:"
@@ -9873,10 +9907,6 @@ msgid "Couldn't create project.godot in project path."
msgstr "無法在項目路徑中創建project.godot。"
#: editor/project_manager.cpp
-msgid "The following files failed extraction from package:"
-msgstr "æå–以下檔案失敗:"
-
-#: editor/project_manager.cpp
#, fuzzy
msgid "Rename Project"
msgstr "é‡å‘½åé …ç›®"
@@ -11115,6 +11145,11 @@ msgstr "讀å–ç¾å­˜çš„ Bus é…置。"
#: editor/script_create_dialog.cpp
#, fuzzy
+msgid "Script file already exists."
+msgstr "Autoload「%sã€å·²ç¶“存在!"
+
+#: editor/script_create_dialog.cpp
+#, fuzzy
msgid "Class Name:"
msgstr "Class:"
@@ -12747,7 +12782,14 @@ msgid "This node has been deprecated. Use AnimationTree instead."
msgstr ""
#: scene/gui/color_picker.cpp
-msgid "Pick a color from the screen."
+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
@@ -12858,6 +12900,12 @@ msgstr ""
msgid "Constants cannot be modified."
msgstr ""
+#~ msgid "Project export failed with error code %d."
+#~ msgstr "專案輸出失敗,錯誤代碼是 %d。"
+
+#~ msgid "Password:"
+#~ msgstr "密碼:"
+
#~ msgid "Pause the scene"
#~ msgstr "æš«åœæ­¤å ´æ™¯"
@@ -13067,10 +13115,6 @@ msgstr ""
#~ msgstr "列:"
#, fuzzy
-#~ msgid "Split already exists."
-#~ msgstr "Autoload「%sã€å·²ç¶“存在!"
-
-#, fuzzy
#~ msgid "Remove Split"
#~ msgstr "移除"
diff --git a/main/SCsub b/main/SCsub
index 73cec1d250..e1efc7e6ed 100644
--- a/main/SCsub
+++ b/main/SCsub
@@ -9,8 +9,8 @@ env.main_sources = []
env.add_source_files(env.main_sources, "*.cpp")
-# order matters here. higher index controller database files write on top of lower index database files
-controller_databases = ["#main/gamecontrollerdb.txt", "#main/gamecontrollerdb_205.txt", "#main/gamecontrollerdb_204.txt", "#main/godotcontrollerdb.txt"]
+# Order matters here. Higher index controller database files write on top of lower index database files.
+controller_databases = ["#main/gamecontrollerdb_204.txt", "#main/gamecontrollerdb_205.txt", "#main/gamecontrollerdb.txt", "#main/godotcontrollerdb.txt"]
env.Depends("#main/default_controller_mappings.gen.cpp", controller_databases)
env.CommandNoCache("#main/default_controller_mappings.gen.cpp", controller_databases, run_in_subprocess(main_builders.make_default_controller_mappings))
diff --git a/main/gamecontrollerdb.txt b/main/gamecontrollerdb.txt
index 5793ebd92d..9f7cd83641 100644
--- a/main/gamecontrollerdb.txt
+++ b/main/gamecontrollerdb.txt
@@ -32,7 +32,7 @@
03000000c82d00006228000000000000,8BitDo SN30 GP,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b4,y:b3,platform:Windows,
03000000c82d00000160000000000000,8BitDo SN30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b4,y:b3,platform:Windows,
03000000c82d00000161000000000000,8BitDo SN30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,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:a5,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,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:a5,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,
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,
@@ -305,6 +305,7 @@
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,
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,
03000000172700004431000000000000,XiaoMi Game Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b20,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a7,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Windows,
03000000786901006e70000000000000,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
@@ -317,6 +318,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
03000000203800000900000000010000,8Bitdo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X,
03000000c82d00000190000001000000,8Bitdo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X,
03000000102800000900000000000000,8Bitdo SFC30 GamePad 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,
+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:a3,righty:a4,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:a3,righty:a4,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,
@@ -367,9 +369,11 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
0300000025090000e803000000000000,Mayflash Wii Classic Controller,a:b1,b:b0,back:b8,dpdown:b13,dpleft:b12,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b2,platform:Mac OS X,
03000000790000000018000000000000,Mayflash WiiU Pro Game Controller Adapter (DInput),a:b4,b:b8,back:b32,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b16,leftstick:b40,lefttrigger:b24,leftx:a0,lefty:a4,rightshoulder:b20,rightstick:b44,righttrigger:b28,rightx:a8,righty:a12,start:b36,x:b0,y:b12,platform:Mac OS X,
03000000d8140000cecf000000000000,MC Cthulhu,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Mac OS X,
+030000005e0400002700000001010000,Microsoft SideWinder Plug & Play Game Pad,a:b0,b:b1,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,lefttrigger:b4,leftx:a0,lefty:a1,righttrigger:b5,x:b2,y:b3,platform:Mac OS X,
03000000d62000007162000001000000,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:Mac OS X,
03000000632500007505000000020000,NEOGEO mini PAD Controller,a:b1,b:b0,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,start:b9,x:b2,y:b3,platform:Mac OS X,
030000001008000001e5000006010000,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:Mac OS X,
+03000000d620000011a7000000020000,Nintendo Switch Core (Plus) Wired Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger: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,
030000007e0500000920000000000000,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:Mac OS X,
030000007e0500000920000001000000,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:Mac OS X,
030000008f0e00000300000000000000,Piranha xtreme,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Mac OS X,
@@ -442,6 +446,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
05000000c82d00000060000000010000,8BitDo SF30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,
05000000c82d00000061000000010000,8Bitdo SF30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,
03000000c82d000021ab000010010000,8BitDo SFC30,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Linux,
+030000003512000012ab000010010000,8Bitdo SFC30 GamePad,a:b2,b:b1,back:b6,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b7,x:b3,y:b0,platform:Linux,
05000000102800000900000000010000,8Bitdo SFC30 GamePad,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Linux,
05000000c82d00003028000000010000,8Bitdo SFC30 GamePad,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Linux,
03000000c82d00000160000000000000,8BitDo SN30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Linux,
@@ -494,6 +499,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
03000000c9110000f055000011010000,HJC Game GAMEPAD,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux,
030000000d0f00000d00000000010000,hori,a:b0,b:b6,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b3,leftx:b4,lefty:b5,rightshoulder:b7,start:b9,x:b1,y:b2,platform:Linux,
030000000d0f00001000000011010000,HORI CO. LTD. FIGHTING STICK 3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux,
+030000000d0f0000c100000011010000,HORI CO. LTD. HORIPAD S,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b13,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
030000000d0f00006a00000011010000,HORI CO. LTD. Real Arcade Pro.4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,
030000000d0f00006b00000011010000,HORI CO. LTD. Real Arcade Pro.4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
030000000d0f00002200000011010000,HORI CO. LTD. REAL ARCADE Pro.V3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux,
@@ -526,6 +532,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
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,
030000006d0400001dc2000014400000,Logitech F310 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,
+030000006d0400001ec2000019200000,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,
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,
@@ -557,9 +564,9 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
030000005e0400000e00000000010000,Microsoft SideWinder,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,rightshoulder:b7,start:b8,x:b3,y:b4,platform:Linux,
030000005e0400008e02000004010000,Microsoft X-Box 360 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,
030000005e0400008e02000062230000,Microsoft X-Box 360 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,
+050000005e040000050b000003090000,Microsoft X-Box One Elite 2 pad,a:b0,b:b1,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a6,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
030000005e040000e302000003020000,Microsoft X-Box One Elite 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,
030000005e040000d102000001010000,Microsoft X-Box One 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,
-050000005e040000050b000003090000,Microsoft X-Box One Elite 2 pad,a:b0,b:b1,y:b4,x:b3,start:b11,guide:b12,back:b17,leftstick:b13,rightstick:b14,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a5,righttrigger:a4,platform:Linux,
030000005e040000dd02000003020000,Microsoft X-Box One pad (Firmware 2015),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
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,
@@ -586,6 +593,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
05000000362800000100000003010000,OUYA Game Controller,a:b0,b:b3,dpdown:b9,dpleft:b10,dpright:b11,dpup:b8,guide:b14,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,x:b1,y:b2,platform:Linux,
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,
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,
+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,
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,
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,
@@ -646,6 +654,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
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,
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,
@@ -664,6 +673,9 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
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,
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,
+05000000110100001914000009010000,SteelSeries Stratus XL,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
03000000ad1b000038f0000090040000,Street Fighter IV FightStick TE,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
03000000666600000488000000010000,Super Joy Box 5 Pro,a:b2,b:b1,back:b9,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Linux,
0300000000f00000f100000000010000,Super RetroPort,a:b1,b:b5,back:b2,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b3,x:b0,y:b4,platform:Linux,
@@ -698,10 +710,12 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
0000000058626f782047616d65706100,Xbox Gamepad (userspace driver),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,
030000005e040000d102000002010000,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,
050000005e040000fd02000030110000,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,
+030000005e040000ea02000000000000,Xbox One Wireless 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,
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,
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,
05000000172700004431000029010000,XiaoMi Game Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b20,leftshoulder:b6,leftstick:b13,lefttrigger:a7,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a6,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Linux,
03000000c0160000e105000001010000,Xin-Mo Xin-Mo Dual Arcade,a:b4,b:b3,back:b6,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b9,leftshoulder:b2,leftx:a0,lefty:a1,rightshoulder:b5,start:b7,x:b1,y:b0,platform:Linux,
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,
diff --git a/main/input_default.cpp b/main/input_default.cpp
index 820069dba3..a13ddeb2b6 100644
--- a/main/input_default.cpp
+++ b/main/input_default.cpp
@@ -727,9 +727,17 @@ InputDefault::InputDefault() {
fallback_mapping = -1;
+ // Parse default mappings.
+ {
+ int i = 0;
+ while (DefaultControllerMappings::mappings[i]) {
+ parse_mapping(DefaultControllerMappings::mappings[i++]);
+ }
+ }
+
+ // If defined, parse SDL_GAMECONTROLLERCONFIG for possible new mappings/overrides.
String env_mapping = OS::get_singleton()->get_environment("SDL_GAMECONTROLLERCONFIG");
if (env_mapping != "") {
-
Vector<String> entries = env_mapping.split("\n");
for (int i = 0; i < entries.size(); i++) {
if (entries[i] == "")
@@ -737,12 +745,6 @@ InputDefault::InputDefault() {
parse_mapping(entries[i]);
}
}
-
- int i = 0;
- while (DefaultControllerMappings::mappings[i]) {
-
- parse_mapping(DefaultControllerMappings::mappings[i++]);
- }
}
void InputDefault::joy_button(int p_device, int p_button, bool p_pressed) {
diff --git a/main/main.cpp b/main/main.cpp
index 2bcea5cb7d..0ff392978a 100644
--- a/main/main.cpp
+++ b/main/main.cpp
@@ -286,11 +286,13 @@ void Main::print_help(const char *p_binary) {
OS::get_singleton()->print(" -s, --script <script> Run a script.\n");
OS::get_singleton()->print(" --check-only Only parse for errors and quit (use with --script).\n");
#ifdef TOOLS_ENABLED
- OS::get_singleton()->print(" --export <target> <path> Export the project using the given export target. Export only main pack if path ends with .pck or .zip. <path> is relative to the project directory.\n");
- OS::get_singleton()->print(" --export-debug <target> <path> Like --export, but use debug template.\n");
+ OS::get_singleton()->print(" --export <preset> <path> Export the project using the given preset and matching release template. The preset name should match one defined in export_presets.cfg.\n");
+ OS::get_singleton()->print(" <path> should be absolute or relative to the project directory, and include the filename for the binary (e.g. 'builds/game.exe'). The target directory should exist.\n");
+ OS::get_singleton()->print(" --export-debug <preset> <path> Same as --export, but using the debug template.\n");
+ OS::get_singleton()->print(" --export-pack <preset> <path> Same as --export, but only export the game pack for the given preset. The <path> extension determines whether it will be in PCK or ZIP format.\n");
OS::get_singleton()->print(" --doctool <path> Dump the engine API reference to the given <path> in XML format, merging if existing files are found.\n");
OS::get_singleton()->print(" --no-docbase Disallow dumping the base types (used with --doctool).\n");
- OS::get_singleton()->print(" --build-solutions Build the scripting solutions (e.g. for C# projects).\n");
+ OS::get_singleton()->print(" --build-solutions Build the scripting solutions (e.g. for C# projects). Implies --editor and requires a valid project to edit.\n");
#ifdef DEBUG_METHODS_ENABLED
OS::get_singleton()->print(" --gdnative-generate-json-api Generate JSON dump of the Godot API for GDNative bindings.\n");
#endif
@@ -673,7 +675,7 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
// We still pass it to the main arguments since the argument handling itself is not done in this function
main_args.push_back(I->get());
#endif
- } else if (I->get() == "--export" || I->get() == "--export-debug") { // Export project
+ } else if (I->get() == "--export" || I->get() == "--export-debug" || I->get() == "--export-pack") { // Export project
editor = true;
main_args.push_back(I->get());
@@ -813,6 +815,13 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
I = N;
}
+#ifdef TOOLS_ENABLED
+ if (editor && project_manager) {
+ OS::get_singleton()->print("Error: Command line arguments implied opening both editor and project manager, which is not possible. Aborting.\n");
+ goto error;
+ }
+#endif
+
// Network file system needs to be configured before globals, since globals are based on the
// 'project.godot' file which will only be available through the network if this is enabled
FileAccessNetwork::configure();
@@ -928,7 +937,7 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
}
}
- if (!project_manager) {
+ if (!project_manager && !editor) {
// Determine if the project manager should be requested
project_manager = main_args.size() == 0 && !found_project;
}
@@ -1393,15 +1402,18 @@ bool Main::start() {
bool hasicon = false;
String doc_tool;
List<String> removal_docs;
-#ifdef TOOLS_ENABLED
- bool doc_base = true;
-#endif
+ String positional_arg;
String game_path;
String script;
String test;
+ bool check_only = false;
+
+#ifdef TOOLS_ENABLED
+ bool doc_base = true;
String _export_preset;
bool export_debug = false;
- bool check_only = false;
+ bool export_pack_only = false;
+#endif
main_timer_sync.init(OS::get_singleton()->get_ticks_usec());
@@ -1418,8 +1430,18 @@ bool Main::start() {
} else if (args[i] == "-p" || args[i] == "--project-manager") {
project_manager = true;
#endif
- } else if (args[i].length() && args[i][0] != '-' && game_path == "") {
- game_path = args[i];
+ } else if (args[i].length() && args[i][0] != '-' && positional_arg == "") {
+ positional_arg = args[i];
+
+ if (args[i].ends_with(".scn") || args[i].ends_with(".tscn") || args[i].ends_with(".escn")) {
+ // Only consider the positional argument to be a scene path if it ends with
+ // a file extension associated with Godot scenes. This makes it possible
+ // for projects to parse command-line arguments for custom CLI arguments
+ // or other file extensions without trouble. This can be used to implement
+ // "drag-and-drop onto executable" logic, which can prove helpful
+ // for non-game applications.
+ game_path = args[i];
+ }
}
//parameters that have an argument to the right
else if (i < (args.size() - 1)) {
@@ -1440,6 +1462,10 @@ bool Main::start() {
editor = true; //needs editor
_export_preset = args[i + 1];
export_debug = true;
+ } else if (args[i] == "--export-pack") {
+ editor = true;
+ _export_preset = args[i + 1];
+ export_pack_only = true;
#endif
} else {
// The parameter does not match anything known, don't skip the next argument
@@ -1509,18 +1535,15 @@ bool Main::start() {
return false;
}
-#endif
-
if (_export_preset != "") {
- if (game_path == "") {
- String err = "Command line param ";
- err += export_debug ? "--export-debug" : "--export";
- err += " passed but no destination path given.\n";
+ if (positional_arg == "") {
+ String err = "Command line includes export parameter option, but no destination path was given.\n";
err += "Please specify the binary's file path to export to. Aborting export.";
- ERR_PRINT(err.utf8().get_data());
+ ERR_PRINT(err);
return false;
}
}
+#endif
if (script == "" && game_path == "" && String(GLOBAL_DEF("application/run/main_scene", "")) != "") {
game_path = GLOBAL_DEF("application/run/main_scene", "");
@@ -1698,20 +1721,14 @@ bool Main::start() {
}
#ifdef TOOLS_ENABLED
-
EditorNode *editor_node = NULL;
if (editor) {
-
editor_node = memnew(EditorNode);
sml->get_root()->add_child(editor_node);
- //root_node->set_editor(editor);
- //startup editor
-
if (_export_preset != "") {
-
- editor_node->export_preset(_export_preset, game_path, export_debug, "", true);
- game_path = ""; //no load anything
+ editor_node->export_preset(_export_preset, positional_arg, export_debug, export_pack_only);
+ game_path = ""; // Do not load anything.
}
}
#endif
@@ -2095,8 +2112,12 @@ bool Main::iteration() {
#ifdef TOOLS_ENABLED
if (auto_build_solutions) {
auto_build_solutions = false;
+ // Only relevant when running the editor.
+ if (!editor) {
+ ERR_FAIL_V_MSG(true, "Command line option --build-solutions was passed, but no project is being edited. Aborting.");
+ }
if (!EditorNode::get_singleton()->call_build()) {
- ERR_FAIL_V(true);
+ ERR_FAIL_V_MSG(true, "Command line option --build-solutions was passed, but the build callback failed. Aborting.");
}
}
#endif
@@ -2148,6 +2169,9 @@ void Main::cleanup() {
ScriptServer::finish_languages();
+ // Sync pending commands that may have been queued from a different thread during ScriptServer finalization
+ VisualServer::get_singleton()->sync();
+
#ifdef TOOLS_ENABLED
EditorNode::unregister_editor_types();
#endif
diff --git a/main/tests/test_gdscript.cpp b/main/tests/test_gdscript.cpp
index 729c5f99cf..a6ef0e9cf4 100644
--- a/main/tests/test_gdscript.cpp
+++ b/main/tests/test_gdscript.cpp
@@ -671,6 +671,30 @@ static void _disassemble_class(const Ref<GDScript> &p_class, const Vector<String
incr += 2;
} break;
+ case GDScriptFunction::OPCODE_ASSIGN_TYPED_BUILTIN: {
+
+ txt += " assign typed builtin (";
+ txt += Variant::get_type_name((Variant::Type)code[ip + 1]);
+ txt += ") ";
+ txt += DADDR(2);
+ txt += " = ";
+ txt += DADDR(3);
+ incr += 4;
+
+ } break;
+ case GDScriptFunction::OPCODE_ASSIGN_TYPED_NATIVE: {
+ Variant className = func.get_constant(code[ip + 1]);
+ GDScriptNativeClass *nc = Object::cast_to<GDScriptNativeClass>(className.operator Object *());
+
+ txt += " assign typed native (";
+ txt += nc->get_name().operator String();
+ txt += ") ";
+ txt += DADDR(2);
+ txt += " = ";
+ txt += DADDR(3);
+ incr += 4;
+
+ } break;
case GDScriptFunction::OPCODE_CAST_TO_SCRIPT: {
txt += " cast ";
diff --git a/methods.py b/methods.py
index 23d66f7f1e..33b8f1cbe7 100644
--- a/methods.py
+++ b/methods.py
@@ -67,8 +67,7 @@ def update_version(module_version_string=""):
f.write("#define VERSION_NAME \"" + str(version.name) + "\"\n")
f.write("#define VERSION_MAJOR " + str(version.major) + "\n")
f.write("#define VERSION_MINOR " + str(version.minor) + "\n")
- if hasattr(version, 'patch'):
- f.write("#define VERSION_PATCH " + str(version.patch) + "\n")
+ f.write("#define VERSION_PATCH " + str(version.patch) + "\n")
f.write("#define VERSION_STATUS \"" + str(version.status) + "\"\n")
f.write("#define VERSION_BUILD \"" + str(build_name) + "\"\n")
f.write("#define VERSION_MODULE_CONFIG \"" + str(version.module_config) + module_version_string + "\"\n")
diff --git a/misc/dist/shell/_godot.zsh-completion b/misc/dist/shell/_godot.zsh-completion
new file mode 100644
index 0000000000..4945ecbabc
--- /dev/null
+++ b/misc/dist/shell/_godot.zsh-completion
@@ -0,0 +1,77 @@
+#compdef godot
+
+# zsh completion for the Godot editor
+# To use it, install this file as `_godot` in a directory specified in your
+# `fpath` environment variable then restart your shell.
+#
+# Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur.
+# Copyright (c) 2014-2020 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.
+
+_arguments \
+ "1::path to scene or 'project.godot' file:_files" \
+ '(-h --help)'{-h,--help}'[display the full help message]' \
+ '--version[display the version string]' \
+ '(-v --verbose)'{-v,--verbose}'[use verbose stdout mode]' \
+ '--quiet[quiet mode, silences stdout messages (errors are still displayed)]' \
+ '(-e --editor)'{-e,--editor}'[start the editor instead of running the scene]' \
+ '(-p --project-manager)'{-p,--project-manager}'[start the project manager, even if a project is auto-detected]' \
+ '(-q --quit)'{-q,--quit}'[quit after the first iteration]' \
+ '(-l --language)'{-l,--language}'[use a specific locale (<locale> being a two-letter code)]:two-letter locale code' \
+ "--path[path to a project (<directory> must contain a 'project.godot' file)]:path to directory with 'project.godot' file:_dirs" \
+ '(-u --upwards)'{-u,--upwards}'[scan folders upwards for project.godot file]' \
+ '--main-pack[path to a pack (.pck) file to load]:path to .pck file:_files' \
+ '--render-thread[set the render thread mode]:render thread mode:(unsafe safe separate)' \
+ '--remote-fs[use a remote filesystem]:remote filesystem address' \
+ '--remote-fs-password[password for remote filesystem]:remote filesystem password' \
+ '--audio-driver[set the audio driver]:audio driver name' \
+ "--video-driver[set the video driver]:video driver name:((GLES3\:'OpenGL ES 3.0 renderer' GLES2\:'OpenGL ES 2.0 renderer'))" \
+ '(-f --fullscreen)'{-f,--fullscreen}'[request fullscreen mode]' \
+ '(-m --maximized)'{-m,--maximized}'[request a maximized window]' \
+ '(-w --windowed)'{-w,--windowed}'[request windowed mode]' \
+ '(-t --always-on-top)'{-t,--always-on-top}'[request an always-on-top window]' \
+ '--resolution[request window resolution]:resolution in WxH format' \
+ '--position[request window position]:position in X,Y format' \
+ '--low-dpi[force low-DPI mode (macOS and Windows only)]' \
+ '--no-window[disable window creation (Windows only), useful together with --script]' \
+ "--enable-vsync-via-compositor[when Vsync is enabled, Vsync via the OS' window compositor (Windows only)]" \
+ "--disable-vsync-via-compositor[disable Vsync via the OS' window compositor (Windows only)]" \
+ '(-d --debug)'{-d,--debug}'[debug (local stdout debugger)]' \
+ '(-b --breakpoints)'{-b,--breakpoints}'[specify the breakpoint list as source::line comma-separated pairs, no spaces (use %20 instead)]:breakpoint list' \
+ '--profiling[enable profiling in the script debugger]' \
+ '--remote-debug[enable remote debugging]:remote debugger address' \
+ '--debug-collisions[show collision shapes when running the scene]' \
+ '--debug-navigation[show navigation polygons when running the scene]' \
+ '--frame-delay[simulate high CPU load (delay each frame by the given number of milliseconds)]:number of milliseconds' \
+ '--time-scale[force time scale (higher values are faster, 1.0 is normal speed)]:time scale' \
+ '--disable-render-loop[disable render loop so rendering only occurs when called explicitly from script]' \
+ '--disable-crash-handler[disable crash handler when supported by the platform code]' \
+ '--fixed-fps[force a fixed number of frames per second (this setting disables real-time synchronization)]:frames per second' \
+ '--print-fps[print the frames per second to the stdout]' \
+ '(-s, --script)'{-s,--script}'[run a script]:path to script:_files' \
+ '--check-only[only parse for errors and quit (use with --script)]' \
+ '--export[export the project using the given preset and matching release template]:export preset name' \
+ '--export-debug[same as --export, but using the debug template]:export preset name' \
+ '--export-pack[same as --export, but only export the game pack for the given preset]:export preset name' \
+ '--doctool[dump the engine API reference to the given path in XML format, merging if existing files are found]:path to base Godot build directory:_dirs' \
+ '--no-docbase[disallow dumping the base types (used with --doctool)]' \
+ '--build-solutions[build the scripting solutions (e.g. for C# projects)]' \
+ '--gdnative-generate-json-api[generate JSON dump of the Godot API for GDNative bindings]' \
+ '--test[run a unit test]:unit test name'
diff --git a/modules/assimp/editor_scene_importer_assimp.cpp b/modules/assimp/editor_scene_importer_assimp.cpp
index 1bc84ce3a0..726f4c1ed0 100644
--- a/modules/assimp/editor_scene_importer_assimp.cpp
+++ b/modules/assimp/editor_scene_importer_assimp.cpp
@@ -732,6 +732,10 @@ void EditorSceneImporterAssimp::_import_animation(ImportState &state, int p_anim
animation->set_name(name);
animation->set_length(anim->mDuration / ticks_per_second);
+ if (name.begins_with("loop") || name.ends_with("loop") || name.begins_with("cycle") || name.ends_with("cycle")) {
+ animation->set_loop(true);
+ }
+
// generate bone stack for animation import
RegenerateBoneStack(state);
diff --git a/modules/assimp/import_utils.h b/modules/assimp/import_utils.h
index f4505249db..c522b01727 100644
--- a/modules/assimp/import_utils.h
+++ b/modules/assimp/import_utils.h
@@ -355,11 +355,13 @@ public:
print_verbose("Open Asset Import: Loading embedded texture " + filename);
if (tex->mHeight == 0) {
if (tex->CheckFormat("png")) {
+ ERR_FAIL_COND_V(Image::_png_mem_loader_func == NULL, Ref<Image>());
Ref<Image> img = Image::_png_mem_loader_func((uint8_t *)tex->pcData, tex->mWidth);
ERR_FAIL_COND_V(img.is_null(), Ref<Image>());
state.path_to_image_cache.insert(p_path, img);
return img;
} else if (tex->CheckFormat("jpg")) {
+ ERR_FAIL_COND_V(Image::_jpg_mem_loader_func == NULL, Ref<Image>());
Ref<Image> img = Image::_jpg_mem_loader_func((uint8_t *)tex->pcData, tex->mWidth);
ERR_FAIL_COND_V(img.is_null(), Ref<Image>());
state.path_to_image_cache.insert(p_path, img);
diff --git a/modules/bullet/SCsub b/modules/bullet/SCsub
index ecc8a9b481..02d0a31a69 100644
--- a/modules/bullet/SCsub
+++ b/modules/bullet/SCsub
@@ -8,7 +8,8 @@ env_bullet = env_modules.Clone()
# Thirdparty source files
if env['builtin_bullet']:
- # Build only version 2 for now (as of 2.87)
+ # Build only version 2 for now (as of 2.89)
+ # Sync file list with relevant upstream CMakeLists.txt for each folder.
thirdparty_dir = "#thirdparty/bullet/"
bullet2_src = [
@@ -67,8 +68,8 @@ if env['builtin_bullet']:
, "BulletCollision/CollisionShapes/btCylinderShape.cpp"
, "BulletCollision/CollisionShapes/btEmptyShape.cpp"
, "BulletCollision/CollisionShapes/btHeightfieldTerrainShape.cpp"
- , "BulletCollision/CollisionShapes/btMinkowskiSumShape.cpp"
, "BulletCollision/CollisionShapes/btMiniSDF.cpp"
+ , "BulletCollision/CollisionShapes/btMinkowskiSumShape.cpp"
, "BulletCollision/CollisionShapes/btMultimaterialTriangleMeshShape.cpp"
, "BulletCollision/CollisionShapes/btMultiSphereShape.cpp"
, "BulletCollision/CollisionShapes/btOptimizedBvh.cpp"
@@ -124,6 +125,8 @@ if env['builtin_bullet']:
, "BulletDynamics/ConstraintSolver/btHingeConstraint.cpp"
, "BulletDynamics/ConstraintSolver/btPoint2PointConstraint.cpp"
, "BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.cpp"
+ , "BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolverMt.cpp"
+ , "BulletDynamics/ConstraintSolver/btBatchedConstraints.cpp"
, "BulletDynamics/ConstraintSolver/btNNCGConstraintSolver.cpp"
, "BulletDynamics/ConstraintSolver/btSliderConstraint.cpp"
, "BulletDynamics/ConstraintSolver/btSolve2LinearConstraint.cpp"
@@ -138,15 +141,17 @@ if env['builtin_bullet']:
, "BulletDynamics/Vehicle/btRaycastVehicle.cpp"
, "BulletDynamics/Vehicle/btWheelInfo.cpp"
, "BulletDynamics/Featherstone/btMultiBody.cpp"
+ , "BulletDynamics/Featherstone/btMultiBodyConstraint.cpp"
, "BulletDynamics/Featherstone/btMultiBodyConstraintSolver.cpp"
, "BulletDynamics/Featherstone/btMultiBodyDynamicsWorld.cpp"
+ , "BulletDynamics/Featherstone/btMultiBodyFixedConstraint.cpp"
+ , "BulletDynamics/Featherstone/btMultiBodyGearConstraint.cpp"
, "BulletDynamics/Featherstone/btMultiBodyJointLimitConstraint.cpp"
- , "BulletDynamics/Featherstone/btMultiBodyConstraint.cpp"
+ , "BulletDynamics/Featherstone/btMultiBodyJointMotor.cpp"
+ , "BulletDynamics/Featherstone/btMultiBodyMLCPConstraintSolver.cpp"
, "BulletDynamics/Featherstone/btMultiBodyPoint2Point.cpp"
- , "BulletDynamics/Featherstone/btMultiBodyFixedConstraint.cpp"
, "BulletDynamics/Featherstone/btMultiBodySliderConstraint.cpp"
- , "BulletDynamics/Featherstone/btMultiBodyJointMotor.cpp"
- , "BulletDynamics/Featherstone/btMultiBodyGearConstraint.cpp"
+ , "BulletDynamics/Featherstone/btMultiBodySphericalJointMotor.cpp"
, "BulletDynamics/MLCPSolvers/btDantzigLCP.cpp"
, "BulletDynamics/MLCPSolvers/btMLCPSolver.cpp"
, "BulletDynamics/MLCPSolvers/btLemkeAlgorithm.cpp"
@@ -167,6 +172,12 @@ if env['builtin_bullet']:
, "BulletSoftBody/btSoftMultiBodyDynamicsWorld.cpp"
, "BulletSoftBody/btSoftSoftCollisionAlgorithm.cpp"
, "BulletSoftBody/btDefaultSoftBodySolver.cpp"
+ , "BulletSoftBody/btDeformableBackwardEulerObjective.cpp"
+ , "BulletSoftBody/btDeformableBodySolver.cpp"
+ , "BulletSoftBody/btDeformableMultiBodyConstraintSolver.cpp"
+ , "BulletSoftBody/btDeformableContactProjection.cpp"
+ , "BulletSoftBody/btDeformableMultiBodyDynamicsWorld.cpp"
+ , "BulletSoftBody/btDeformableContactConstraint.cpp"
# clew
, "clew/clew.c"
@@ -182,6 +193,9 @@ if env['builtin_bullet']:
, "LinearMath/btSerializer64.cpp"
, "LinearMath/btThreads.cpp"
, "LinearMath/btVector3.cpp"
+ , "LinearMath/TaskScheduler/btTaskScheduler.cpp"
+ , "LinearMath/TaskScheduler/btThreadSupportPosix.cpp"
+ , "LinearMath/TaskScheduler/btThreadSupportWin32.cpp"
]
thirdparty_sources = [thirdparty_dir + file for file in bullet2_src]
diff --git a/modules/bullet/space_bullet.cpp b/modules/bullet/space_bullet.cpp
index e5b2ac3808..0f50d31611 100644
--- a/modules/bullet/space_bullet.cpp
+++ b/modules/bullet/space_bullet.cpp
@@ -945,7 +945,7 @@ bool SpaceBullet::test_body_motion(RigidBodyBullet *p_body, const Transform &p_f
btVector3 motion;
G_TO_B(p_motion, motion);
- if (!motion.fuzzyZero()) {
+ {
// Phase two - sweep test, from a secure position without margin
const int shape_count(p_body->get_shape_count());
@@ -960,7 +960,7 @@ bool SpaceBullet::test_body_motion(RigidBodyBullet *p_body, const Transform &p_f
motionVec->end();
#endif
- for (int shIndex = 0; shIndex < shape_count; ++shIndex) {
+ for (int shIndex = 0; shIndex < shape_count && !motion.fuzzyZero(); ++shIndex) {
if (p_body->is_shape_disabled(shIndex)) {
continue;
}
diff --git a/modules/enet/doc_classes/NetworkedMultiplayerENet.xml b/modules/enet/doc_classes/NetworkedMultiplayerENet.xml
index 78a8e94012..9509adfb18 100644
--- a/modules/enet/doc_classes/NetworkedMultiplayerENet.xml
+++ b/modules/enet/doc_classes/NetworkedMultiplayerENet.xml
@@ -49,7 +49,7 @@
<argument index="3" name="out_bandwidth" type="int" default="0">
</argument>
<description>
- Create server that listens to connections via [code]port[/code]. The port needs to be an available, unused port between 0 and 65535. Note that ports below 1024 are privileged and may require elevated permissions depending on the platform. To change the interface the server listens on, use [method set_bind_ip]. The default IP is the wildcard [code]"*"[/code], which listens on all available interfaces. [code]max_clients[/code] is the maximum number of clients that are allowed at once, any number up to 4096 may be used, although the achievable number of simultaneous clients may be far lower and depends on the application. For additional details on the bandwidth parameters, see [method create_client]. Returns [constant OK] if a server was created, [constant ERR_ALREADY_IN_USE] if this NetworkedMultiplayerENet instance already has an open connection (in which case you need to call [method close_connection] first) or [constant ERR_CANT_CREATE] if the server could not be created.
+ Create server that listens to connections via [code]port[/code]. The port needs to be an available, unused port between 0 and 65535. Note that ports below 1024 are privileged and may require elevated permissions depending on the platform. To change the interface the server listens on, use [method set_bind_ip]. The default IP is the wildcard [code]"*"[/code], which listens on all available interfaces. [code]max_clients[/code] is the maximum number of clients that are allowed at once, any number up to 4095 may be used, although the achievable number of simultaneous clients may be far lower and depends on the application. For additional details on the bandwidth parameters, see [method create_client]. Returns [constant OK] if a server was created, [constant ERR_ALREADY_IN_USE] if this NetworkedMultiplayerENet instance already has an open connection (in which case you need to call [method close_connection] first) or [constant ERR_CANT_CREATE] if the server could not be created.
</description>
</method>
<method name="disconnect_peer">
diff --git a/modules/enet/networked_multiplayer_enet.cpp b/modules/enet/networked_multiplayer_enet.cpp
index 35c7429d1e..21dd758391 100644
--- a/modules/enet/networked_multiplayer_enet.cpp
+++ b/modules/enet/networked_multiplayer_enet.cpp
@@ -75,7 +75,7 @@ Error NetworkedMultiplayerENet::create_server(int p_port, int p_max_clients, int
ERR_FAIL_COND_V(active, ERR_ALREADY_IN_USE);
ERR_FAIL_COND_V(p_port < 0 || p_port > 65535, ERR_INVALID_PARAMETER);
- ERR_FAIL_COND_V(p_max_clients < 0, ERR_INVALID_PARAMETER);
+ ERR_FAIL_COND_V(p_max_clients < 1 || p_max_clients > 4095, ERR_INVALID_PARAMETER);
ERR_FAIL_COND_V(p_in_bandwidth < 0, ERR_INVALID_PARAMETER);
ERR_FAIL_COND_V(p_out_bandwidth < 0, ERR_INVALID_PARAMETER);
diff --git a/modules/etc/image_etc.cpp b/modules/etc/image_etc.cpp
index f0b95c893d..b80138c99d 100644
--- a/modules/etc/image_etc.cpp
+++ b/modules/etc/image_etc.cpp
@@ -139,11 +139,16 @@ static void _compress_etc(Image *p_img, float p_lossy_quality, bool force_etc1_f
return;
}
- if (img_format >= Image::FORMAT_RGBA8 && force_etc1_format) {
- // If VRAM compression is using ETC, but image has alpha, convert to RGBA4444
+ if (force_etc1_format) {
+ // If VRAM compression is using ETC, but image has alpha, convert to RGBA4444 or LA8
// This saves space while maintaining the alpha channel
- p_img->convert(Image::FORMAT_RGBA4444);
- return;
+ if (detected_channels == Image::DETECTED_RGBA) {
+ p_img->convert(Image::FORMAT_RGBA4444);
+ return;
+ } else if (detected_channels == Image::DETECTED_LA) {
+ p_img->convert(Image::FORMAT_LA8);
+ return;
+ }
}
uint32_t imgw = p_img->get_width(), imgh = p_img->get_height();
diff --git a/modules/gdnative/gdnative/gdnative.cpp b/modules/gdnative/gdnative/gdnative.cpp
index 6ef1f2f4b9..06334556d9 100644
--- a/modules/gdnative/gdnative/gdnative.cpp
+++ b/modules/gdnative/gdnative/gdnative.cpp
@@ -170,6 +170,10 @@ bool GDAPI godot_is_instance_valid(const godot_object *p_object) {
return ObjectDB::instance_validate((Object *)p_object);
}
+godot_object GDAPI *godot_instance_from_id(godot_int p_instance_id) {
+ return (godot_object *)ObjectDB::get_instance((ObjectID)p_instance_id);
+}
+
void *godot_get_class_tag(const godot_string_name *p_class) {
StringName class_name = *(StringName *)p_class;
ClassDB::ClassInfo *class_info = ClassDB::classes.getptr(class_name);
diff --git a/modules/gdnative/gdnative_api.json b/modules/gdnative/gdnative_api.json
index 7e2ca49f8d..8ccb8d2286 100644
--- a/modules/gdnative/gdnative_api.json
+++ b/modules/gdnative/gdnative_api.json
@@ -155,6 +155,13 @@
["const godot_object *", "p_object"],
["void *", "p_class_tag"]
]
+ },
+ {
+ "name": "godot_instance_from_id",
+ "return_type": "godot_object *",
+ "arguments": [
+ ["godot_int", "p_instance_id"]
+ ]
}
]
},
diff --git a/modules/gdnative/include/gdnative/gdnative.h b/modules/gdnative/include/gdnative/gdnative.h
index 2fe59b8a73..e19a2ec149 100644
--- a/modules/gdnative/include/gdnative/gdnative.h
+++ b/modules/gdnative/include/gdnative/gdnative.h
@@ -290,6 +290,9 @@ bool GDAPI godot_is_instance_valid(const godot_object *p_object);
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);
+// equivalent of GDScript's instance_from_id
+godot_object GDAPI *godot_instance_from_id(godot_int p_instance_id);
+
#ifdef __cplusplus
}
#endif
diff --git a/modules/gdscript/gdscript.cpp b/modules/gdscript/gdscript.cpp
index 5b0210b16d..a255b92257 100644
--- a/modules/gdscript/gdscript.cpp
+++ b/modules/gdscript/gdscript.cpp
@@ -320,7 +320,7 @@ ScriptInstance *GDScript::instance_create(Object *p_this) {
if (!ClassDB::is_parent_class(p_this->get_class_name(), top->native->get_name())) {
if (ScriptDebugger::get_singleton()) {
- GDScriptLanguage::get_singleton()->debug_break_parse(get_path(), 0, "Script inherits from native type '" + String(top->native->get_name()) + "', so it can't be instanced in object of type: '" + p_this->get_class() + "'");
+ GDScriptLanguage::get_singleton()->debug_break_parse(get_path(), 1, "Script inherits from native type '" + String(top->native->get_name()) + "', so it can't be instanced in object of type: '" + p_this->get_class() + "'");
}
ERR_FAIL_V_MSG(NULL, "Script inherits from native type '" + String(top->native->get_name()) + "', so it can't be instanced in object of type '" + p_this->get_class() + "'" + ".");
}
@@ -915,14 +915,43 @@ GDScript::GDScript() :
#endif
}
+void GDScript::_save_orphaned_subclasses() {
+ struct ClassRefWithName {
+ ObjectID id;
+ String fully_qualified_name;
+ };
+ Vector<ClassRefWithName> weak_subclasses;
+ // collect subclasses ObjectID and name
+ for (Map<StringName, Ref<GDScript> >::Element *E = subclasses.front(); E; E = E->next()) {
+ E->get()->_owner = NULL; //bye, you are no longer owned cause I died
+ ClassRefWithName subclass;
+ subclass.id = E->get()->get_instance_id();
+ subclass.fully_qualified_name = E->get()->fully_qualified_name;
+ weak_subclasses.push_back(subclass);
+ }
+
+ // clear subclasses to allow unused subclasses to be deleted
+ subclasses.clear();
+ // subclasses are also held by constants, clear those as well
+ constants.clear();
+
+ // keep orphan subclass only for subclasses that are still in use
+ for (int i = 0; i < weak_subclasses.size(); i++) {
+ ClassRefWithName subclass = weak_subclasses[i];
+ Object *obj = ObjectDB::get_instance(subclass.id);
+ if (!obj)
+ continue;
+ // subclass is not released
+ GDScriptLanguage::get_singleton()->add_orphan_subclass(subclass.fully_qualified_name, subclass.id);
+ }
+}
+
GDScript::~GDScript() {
for (Map<StringName, GDScriptFunction *>::Element *E = member_functions.front(); E; E = E->next()) {
memdelete(E->get());
}
- for (Map<StringName, Ref<GDScript> >::Element *E = subclasses.front(); E; E = E->next()) {
- E->get()->_owner = NULL; //bye, you are no longer owned cause I died
- }
+ _save_orphaned_subclasses();
#ifdef DEBUG_ENABLED
if (GDScriptLanguage::get_singleton()->lock) {
@@ -2051,6 +2080,9 @@ String GDScriptWarning::get_message() const {
CHECK_SYMBOLS(2);
return "The '" + symbols[0] + "' keyword is deprecated and will be removed in a future release, please replace its uses by '" + symbols[1] + "'.";
} break;
+ case STANDALONE_TERNARY: {
+ return "Standalone ternary conditional operator: the return value is being discarded.";
+ }
case WARNING_MAX: break; // Can't happen, but silences warning
}
ERR_FAIL_V_MSG(String(), "Invalid GDScript warning code: " + get_name_from_code(code) + ".");
@@ -2092,6 +2124,7 @@ String GDScriptWarning::get_name_from_code(Code p_code) {
"UNSAFE_CAST",
"UNSAFE_CALL_ARGUMENT",
"DEPRECATED_KEYWORD",
+ "STANDALONE_TERNARY",
NULL
};
@@ -2172,6 +2205,22 @@ GDScriptLanguage::~GDScriptLanguage() {
singleton = NULL;
}
+void GDScriptLanguage::add_orphan_subclass(const String &p_qualified_name, const ObjectID &p_subclass) {
+ orphan_subclasses[p_qualified_name] = p_subclass;
+}
+
+Ref<GDScript> GDScriptLanguage::get_orphan_subclass(const String &p_qualified_name) {
+ Map<String, ObjectID>::Element *orphan_subclass_element = orphan_subclasses.find(p_qualified_name);
+ if (!orphan_subclass_element)
+ return Ref<GDScript>();
+ ObjectID orphan_subclass = orphan_subclass_element->get();
+ Object *obj = ObjectDB::get_instance(orphan_subclass);
+ orphan_subclasses.erase(orphan_subclass_element);
+ if (!obj)
+ return Ref<GDScript>();
+ return Ref<GDScript>(Object::cast_to<GDScript>(obj));
+}
+
/*************** RESOURCE ***************/
RES ResourceFormatLoaderGDScript::load(const String &p_path, const String &p_original_path, Error *r_error) {
diff --git a/modules/gdscript/gdscript.h b/modules/gdscript/gdscript.h
index cc25c1c313..4ae52238ce 100644
--- a/modules/gdscript/gdscript.h
+++ b/modules/gdscript/gdscript.h
@@ -111,6 +111,7 @@ class GDScript : public Script {
String source;
String path;
String name;
+ String fully_qualified_name;
SelfList<GDScript> script_list;
GDScriptInstance *_create_instance(const Variant **p_args, int p_argcount, Object *p_owner, bool p_isref, Variant::CallError &r_error);
@@ -131,6 +132,8 @@ class GDScript : public Script {
bool _update_exports();
+ void _save_orphaned_subclasses();
+
protected:
bool _get(const StringName &p_name, Variant &r_ret) const;
bool _set(const StringName &p_name, const Variant &p_value);
@@ -297,6 +300,7 @@ struct GDScriptWarning {
UNSAFE_CAST, // Cast used in an unknown type
UNSAFE_CALL_ARGUMENT, // Function call argument is of a supertype of the require argument
DEPRECATED_KEYWORD, // The keyword is deprecated and should be replaced
+ STANDALONE_TERNARY, // Return value of ternary expression is discarded
WARNING_MAX,
} code;
Vector<String> symbols;
@@ -353,6 +357,8 @@ class GDScriptLanguage : public ScriptLanguage {
bool profiling;
uint64_t script_frame_time;
+ Map<String, ObjectID> orphan_subclasses;
+
public:
int calls;
@@ -504,6 +510,9 @@ public:
virtual bool handles_global_class_type(const String &p_type) const;
virtual String get_global_class_name(const String &p_path, String *r_base_type = NULL, String *r_icon_path = NULL) const;
+ void add_orphan_subclass(const String &p_qualified_name, const ObjectID &p_subclass);
+ Ref<GDScript> get_orphan_subclass(const String &p_qualified_name);
+
GDScriptLanguage();
~GDScriptLanguage();
};
diff --git a/modules/gdscript/gdscript_compiler.cpp b/modules/gdscript/gdscript_compiler.cpp
index 11e015b473..fba1b992ec 100644
--- a/modules/gdscript/gdscript_compiler.cpp
+++ b/modules/gdscript/gdscript_compiler.cpp
@@ -90,11 +90,11 @@ bool GDScriptCompiler::_create_unary_operator(CodeGen &codegen, const GDScriptPa
return true;
}
-bool GDScriptCompiler::_create_binary_operator(CodeGen &codegen, const GDScriptParser::OperatorNode *on, Variant::Operator op, int p_stack_level, bool p_initializer) {
+bool GDScriptCompiler::_create_binary_operator(CodeGen &codegen, const GDScriptParser::OperatorNode *on, Variant::Operator op, int p_stack_level, bool p_initializer, int p_index_addr) {
ERR_FAIL_COND_V(on->arguments.size() != 2, false);
- int src_address_a = _parse_expression(codegen, on->arguments[0], p_stack_level, false, p_initializer);
+ int src_address_a = _parse_expression(codegen, on->arguments[0], p_stack_level, false, p_initializer, p_index_addr);
if (src_address_a < 0)
return false;
if (src_address_a & GDScriptFunction::ADDR_TYPE_STACK << GDScriptFunction::ADDR_BITS)
@@ -171,7 +171,7 @@ GDScriptDataType GDScriptCompiler::_gdtype_from_datatype(const GDScriptParser::D
return result;
}
-int GDScriptCompiler::_parse_assign_right_expression(CodeGen &codegen, const GDScriptParser::OperatorNode *p_expression, int p_stack_level) {
+int GDScriptCompiler::_parse_assign_right_expression(CodeGen &codegen, const GDScriptParser::OperatorNode *p_expression, int p_stack_level, int p_index_addr) {
Variant::Operator var_op = Variant::OP_MAX;
@@ -205,7 +205,7 @@ int GDScriptCompiler::_parse_assign_right_expression(CodeGen &codegen, const GDS
return _parse_expression(codegen, p_expression->arguments[1], p_stack_level, false, initializer);
}
- if (!_create_binary_operator(codegen, p_expression, var_op, p_stack_level, initializer))
+ if (!_create_binary_operator(codegen, p_expression, var_op, p_stack_level, initializer, p_index_addr))
return -1;
int dst_addr = (p_stack_level) | (GDScriptFunction::ADDR_TYPE_STACK << GDScriptFunction::ADDR_BITS);
@@ -214,7 +214,7 @@ int GDScriptCompiler::_parse_assign_right_expression(CodeGen &codegen, const GDS
return dst_addr;
}
-int GDScriptCompiler::_parse_expression(CodeGen &codegen, const GDScriptParser::Node *p_expression, int p_stack_level, bool p_root, bool p_initializer) {
+int GDScriptCompiler::_parse_expression(CodeGen &codegen, const GDScriptParser::Node *p_expression, int p_stack_level, bool p_root, bool p_initializer, int p_index_addr) {
switch (p_expression->type) {
//should parse variable declaration and adjust stack accordingly...
@@ -704,7 +704,9 @@ int GDScriptCompiler::_parse_expression(CodeGen &codegen, const GDScriptParser::
return from;
int index;
- if (named) {
+ if (p_index_addr != 0) {
+ index = p_index_addr;
+ } else if (named) {
if (on->arguments[0]->type == GDScriptParser::Node::TYPE_SELF && codegen.script && codegen.function_node && !codegen.function_node->_static) {
GDScriptParser::IdentifierNode *identifier = static_cast<GDScriptParser::IdentifierNode *>(on->arguments[1]);
@@ -1091,7 +1093,7 @@ int GDScriptCompiler::_parse_expression(CodeGen &codegen, const GDScriptParser::
codegen.alloc_stack(slevel);
}
- int set_value = _parse_assign_right_expression(codegen, on, slevel + 1);
+ int set_value = _parse_assign_right_expression(codegen, on, slevel + 1, named ? 0 : set_index);
if (set_value < 0) //error
return set_value;
@@ -2121,14 +2123,21 @@ void GDScriptCompiler::_make_scripts(GDScript *p_script, const GDScriptParser::C
StringName name = p_class->subclasses[i]->name;
Ref<GDScript> subclass;
+ String fully_qualified_name = p_script->fully_qualified_name + "::" + name;
if (old_subclasses.has(name)) {
subclass = old_subclasses[name];
} else {
- subclass.instance();
+ Ref<GDScript> orphan_subclass = GDScriptLanguage::get_singleton()->get_orphan_subclass(fully_qualified_name);
+ if (orphan_subclass.is_valid()) {
+ subclass = orphan_subclass;
+ } else {
+ subclass.instance();
+ }
}
subclass->_owner = p_script;
+ subclass->fully_qualified_name = fully_qualified_name;
p_script->subclasses.insert(name, subclass);
_make_scripts(subclass.ptr(), p_class->subclasses[i], false);
@@ -2147,6 +2156,9 @@ Error GDScriptCompiler::compile(const GDScriptParser *p_parser, GDScript *p_scri
source = p_script->get_path();
+ // The best fully qualified name for a base level script is its file path
+ p_script->fully_qualified_name = p_script->path;
+
// Create scripts for subclasses beforehand so they can be referenced
_make_scripts(p_script, static_cast<const GDScriptParser::ClassNode *>(root), p_keep_state);
diff --git a/modules/gdscript/gdscript_compiler.h b/modules/gdscript/gdscript_compiler.h
index bb3ee881f8..7d5234a023 100644
--- a/modules/gdscript/gdscript_compiler.h
+++ b/modules/gdscript/gdscript_compiler.h
@@ -140,12 +140,12 @@ class GDScriptCompiler {
void _set_error(const String &p_error, const GDScriptParser::Node *p_node);
bool _create_unary_operator(CodeGen &codegen, const GDScriptParser::OperatorNode *on, Variant::Operator op, int p_stack_level);
- bool _create_binary_operator(CodeGen &codegen, const GDScriptParser::OperatorNode *on, Variant::Operator op, int p_stack_level, bool p_initializer = false);
+ bool _create_binary_operator(CodeGen &codegen, const GDScriptParser::OperatorNode *on, Variant::Operator op, int p_stack_level, bool p_initializer = false, int p_index_addr = 0);
GDScriptDataType _gdtype_from_datatype(const GDScriptParser::DataType &p_datatype) const;
- int _parse_assign_right_expression(CodeGen &codegen, const GDScriptParser::OperatorNode *p_expression, int p_stack_level);
- int _parse_expression(CodeGen &codegen, const GDScriptParser::Node *p_expression, int p_stack_level, bool p_root = false, bool p_initializer = false);
+ int _parse_assign_right_expression(CodeGen &codegen, const GDScriptParser::OperatorNode *p_expression, int p_stack_level, int p_index_addr = 0);
+ int _parse_expression(CodeGen &codegen, const GDScriptParser::Node *p_expression, int p_stack_level, bool p_root = false, bool p_initializer = false, int p_index_addr = 0);
Error _parse_block(CodeGen &codegen, const GDScriptParser::BlockNode *p_block, int p_stack_level = 0, int p_break_addr = -1, int p_continue_addr = -1);
Error _parse_function(GDScript *p_script, const GDScriptParser::ClassNode *p_class, const GDScriptParser::FunctionNode *p_func, bool p_for_ready = false);
Error _parse_class_level(GDScript *p_script, const GDScriptParser::ClassNode *p_class, bool p_keep_state);
diff --git a/modules/gdscript/gdscript_editor.cpp b/modules/gdscript/gdscript_editor.cpp
index e2f2b7fc3b..65c61cb57c 100644
--- a/modules/gdscript/gdscript_editor.cpp
+++ b/modules/gdscript/gdscript_editor.cpp
@@ -335,7 +335,9 @@ void GDScriptLanguage::debug_get_stack_level_members(int p_level, List<String> *
ScriptInstance *GDScriptLanguage::debug_get_stack_level_instance(int p_level) {
- ERR_FAIL_COND_V(_debug_parse_err_line >= 0, NULL);
+ if (_debug_parse_err_line >= 0)
+ return NULL;
+
ERR_FAIL_INDEX_V(p_level, _debug_call_stack_pos, NULL);
int l = _debug_call_stack_pos - p_level - 1;
@@ -555,7 +557,7 @@ static String _get_visual_datatype(const PropertyInfo &p_info, bool p_isarg = tr
}
if (p_info.type == Variant::NIL) {
if (p_isarg || (p_info.usage & PROPERTY_USAGE_NIL_IS_VARIANT)) {
- return "var";
+ return "Variant";
} else {
return "void";
}
@@ -1736,14 +1738,12 @@ static String _make_arguments_hint(const MethodInfo &p_info, int p_arg_idx) {
for (const List<PropertyInfo>::Element *E = p_info.arguments.front(); E; E = E->next()) {
if (i > 0) {
arghint += ", ";
- } else {
- arghint += " ";
}
if (i == p_arg_idx) {
arghint += String::chr(0xFFFF);
}
- arghint += _get_visual_datatype(E->get(), true) + " " + E->get().name;
+ arghint += E->get().name + ": " + _get_visual_datatype(E->get(), true);
if (i - def_args >= 0) {
arghint += String(" = ") + p_info.default_arguments[i - def_args].get_construct_string();
@@ -1759,8 +1759,6 @@ static String _make_arguments_hint(const MethodInfo &p_info, int p_arg_idx) {
if (p_info.flags & METHOD_FLAG_VARARG) {
if (p_info.arguments.size() > 0) {
arghint += ", ";
- } else {
- arghint += " ";
}
if (p_arg_idx >= p_info.arguments.size()) {
arghint += String::chr(0xFFFF);
@@ -1770,9 +1768,6 @@ static String _make_arguments_hint(const MethodInfo &p_info, int p_arg_idx) {
arghint += String::chr(0xFFFF);
}
}
- if (p_info.arguments.size() > 0 || (p_info.flags & METHOD_FLAG_VARARG)) {
- arghint += " ";
- }
arghint += ")";
@@ -1787,14 +1782,12 @@ static String _make_arguments_hint(const GDScriptParser::FunctionNode *p_functio
for (int i = 0; i < p_function->arguments.size(); i++) {
if (i > 0) {
arghint += ", ";
- } else {
- arghint += " ";
}
if (i == p_arg_idx) {
arghint += String::chr(0xFFFF);
}
- arghint += p_function->argument_types[i].to_string() + " " + p_function->arguments[i].operator String();
+ arghint += p_function->arguments[i].operator String() + ": " + p_function->argument_types[i].to_string();
if (i - def_args >= 0) {
String def_val = "<unknown>";
@@ -1818,9 +1811,6 @@ static String _make_arguments_hint(const GDScriptParser::FunctionNode *p_functio
}
}
- if (p_function->arguments.size() > 0) {
- arghint += " ";
- }
arghint += ")";
return arghint;
diff --git a/modules/gdscript/gdscript_function.cpp b/modules/gdscript/gdscript_function.cpp
index a01a7397fe..eef39da8b5 100644
--- a/modules/gdscript/gdscript_function.cpp
+++ b/modules/gdscript/gdscript_function.cpp
@@ -500,6 +500,13 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
Object *obj_A = *a;
Object *obj_B = *b;
+#ifdef DEBUG_ENABLED
+ if (!ObjectDB::instance_validate(obj_A)) {
+ err_text = "Left operand of 'is' was already freed.";
+ OPCODE_BREAK;
+ }
+#endif // DEBUG_ENABLED
+
GDScript *scr_B = Object::cast_to<GDScript>(obj_B);
if (scr_B) {
diff --git a/modules/gdscript/gdscript_function.h b/modules/gdscript/gdscript_function.h
index 236ca720a2..ad95ebc543 100644
--- a/modules/gdscript/gdscript_function.h
+++ b/modules/gdscript/gdscript_function.h
@@ -76,14 +76,17 @@ struct GDScriptDataType {
if (p_variant.get_type() != Variant::OBJECT) {
return false;
}
+
Object *obj = p_variant.operator Object *();
- if (obj) {
- if (!ClassDB::is_parent_class(obj->get_class_name(), native_type)) {
- // Try with underscore prefix
- StringName underscore_native_type = "_" + native_type;
- if (!ClassDB::is_parent_class(obj->get_class_name(), underscore_native_type)) {
- return false;
- }
+ if (!obj || !ObjectDB::instance_validate(obj)) {
+ return false;
+ }
+
+ if (!ClassDB::is_parent_class(obj->get_class_name(), native_type)) {
+ // Try with underscore prefix
+ StringName underscore_native_type = "_" + native_type;
+ if (!ClassDB::is_parent_class(obj->get_class_name(), underscore_native_type)) {
+ return false;
}
}
return true;
@@ -96,7 +99,12 @@ struct GDScriptDataType {
if (p_variant.get_type() != Variant::OBJECT) {
return false;
}
+
Object *obj = p_variant.operator Object *();
+ if (!obj || !ObjectDB::instance_validate(obj)) {
+ return false;
+ }
+
Ref<Script> base = obj && obj->get_script_instance() ? obj->get_script_instance()->get_script() : NULL;
bool valid = false;
while (base.is_valid()) {
diff --git a/modules/gdscript/gdscript_functions.cpp b/modules/gdscript/gdscript_functions.cpp
index e0e95f259e..01d62a1c62 100644
--- a/modules/gdscript/gdscript_functions.cpp
+++ b/modules/gdscript/gdscript_functions.cpp
@@ -2057,12 +2057,13 @@ MethodInfo GDScriptFunctions::get_info(Function p_func) {
mi.return_val.type = Variant::BOOL;
return mi;
} break;
- case FUNC_MAX: {
+ default: {
ERR_FAIL_V(MethodInfo());
} break;
}
#endif
-
- return MethodInfo();
+ MethodInfo mi;
+ mi.return_val.usage |= PROPERTY_USAGE_NIL_IS_VARIANT;
+ return mi;
}
diff --git a/modules/gdscript/gdscript_parser.cpp b/modules/gdscript/gdscript_parser.cpp
index 112569a8d6..5c2e7137bf 100644
--- a/modules/gdscript/gdscript_parser.cpp
+++ b/modules/gdscript/gdscript_parser.cpp
@@ -2689,6 +2689,7 @@ void GDScriptParser::_transform_match_statment(MatchNode *p_match_statement) {
op->op = OperatorNode::OP_ASSIGN;
op->arguments.push_back(id2);
op->arguments.push_back(local_var->assign);
+ local_var->assign_op = op;
branch->body->statements.push_front(op);
branch->body->statements.push_front(local_var);
@@ -2866,7 +2867,6 @@ void GDScriptParser::_parse_block(BlockNode *p_block, bool p_static) {
assigned = _get_default_value_for_type(lv->datatype, var_line);
}
- lv->assign = assigned;
//must be added later, to avoid self-referencing.
p_block->variables.insert(n, lv);
@@ -4741,10 +4741,6 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
member.line = tokenizer->get_token_line();
member.usages = 0;
member.rpc_mode = rpc_mode;
-#ifdef TOOLS_ENABLED
- Variant::CallError ce;
- member.default_value = Variant::construct(member._export.type, NULL, 0, ce);
-#endif
if (current_class->constant_expressions.has(member.identifier)) {
_set_error("A constant named \"" + String(member.identifier) + "\" already exists in this class (at line: " +
@@ -4797,6 +4793,32 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
}
}
+ if (autoexport && member.data_type.has_type) {
+ if (member.data_type.kind == DataType::BUILTIN) {
+ member._export.type = member.data_type.builtin_type;
+ } else if (member.data_type.kind == DataType::NATIVE) {
+ if (ClassDB::is_parent_class(member.data_type.native_type, "Resource")) {
+ member._export.type = Variant::OBJECT;
+ member._export.hint = PROPERTY_HINT_RESOURCE_TYPE;
+ member._export.usage |= PROPERTY_USAGE_SCRIPT_VARIABLE;
+ member._export.hint_string = member.data_type.native_type;
+ member._export.class_name = member.data_type.native_type;
+ } else {
+ _set_error("Invalid export type. Only built-in and native resource types can be exported.", member.line);
+ return;
+ }
+
+ } else {
+ _set_error("Invalid export type. Only built-in and native resource types can be exported.", member.line);
+ return;
+ }
+ }
+
+#ifdef TOOLS_ENABLED
+ Variant::CallError ce;
+ member.default_value = Variant::construct(member._export.type, NULL, 0, ce);
+#endif
+
if (tokenizer->get_token() == GDScriptTokenizer::TK_OP_ASSIGN) {
#ifdef DEBUG_ENABLED
@@ -4930,27 +4952,6 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
member.initial_assignment = op;
}
- if (autoexport && member.data_type.has_type) {
- if (member.data_type.kind == DataType::BUILTIN) {
- member._export.type = member.data_type.builtin_type;
- } else if (member.data_type.kind == DataType::NATIVE) {
- if (ClassDB::is_parent_class(member.data_type.native_type, "Resource")) {
- member._export.type = Variant::OBJECT;
- member._export.hint = PROPERTY_HINT_RESOURCE_TYPE;
- member._export.usage |= PROPERTY_USAGE_SCRIPT_VARIABLE;
- member._export.hint_string = member.data_type.native_type;
- member._export.class_name = member.data_type.native_type;
- } else {
- _set_error("Invalid export type. Only built-in and native resource types can be exported.", member.line);
- return;
- }
-
- } else {
- _set_error("Invalid export type. Only built-in and native resource types can be exported.", member.line);
- return;
- }
- }
-
if (tokenizer->get_token() == GDScriptTokenizer::TK_PR_SETGET) {
tokenizer->advance();
@@ -6965,6 +6966,17 @@ GDScriptParser::DataType GDScriptParser::_reduce_function_call_type(const Operat
if (error_set) return DataType();
+ // Special case: check copy constructor. Those are defined implicitly in Variant.
+ if (par_types.size() == 1) {
+ if (!par_types[0].has_type || (par_types[0].kind == DataType::BUILTIN && par_types[0].builtin_type == tn->vtype)) {
+ DataType result;
+ result.has_type = true;
+ result.kind = DataType::BUILTIN;
+ result.builtin_type = tn->vtype;
+ return result;
+ }
+ }
+
bool match = false;
List<MethodInfo> constructors;
Variant::get_constructor_list(tn->vtype, &constructors);
@@ -7035,12 +7047,10 @@ GDScriptParser::DataType GDScriptParser::_reduce_function_call_type(const Operat
return_type = _type_from_property(mi.return_val, false);
-#ifdef DEBUG_ENABLED
// Check all arguments beforehand to solve warnings
for (int i = 1; i < p_call->arguments.size(); i++) {
_reduce_node_type(p_call->arguments[i]);
}
-#endif // DEBUG_ENABLED
// Check arguments
@@ -7068,12 +7078,10 @@ GDScriptParser::DataType GDScriptParser::_reduce_function_call_type(const Operat
ERR_FAIL_V(DataType());
}
-#ifdef DEBUG_ENABLED
// Check all arguments beforehand to solve warnings
for (int i = arg_id + 1; i < p_call->arguments.size(); i++) {
_reduce_node_type(p_call->arguments[i]);
}
-#endif // DEBUG_ENABLED
IdentifierNode *func_id = static_cast<IdentifierNode *>(p_call->arguments[arg_id]);
callee_name = func_id->name;
@@ -7637,6 +7645,11 @@ GDScriptParser::DataType GDScriptParser::_reduce_identifier_type(const DataType
void GDScriptParser::_check_class_level_types(ClassNode *p_class) {
+ // Names of internal object properties that we check to avoid overriding them.
+ // "__meta__" could also be in here, but since it doesn't really affect object metadata,
+ // it is okay to override it on script.
+ StringName script_name = CoreStringNames::get_singleton()->_script;
+
_mark_line_as_safe(p_class->line);
// Constants
@@ -7657,8 +7670,9 @@ void GDScriptParser::_check_class_level_types(ClassNode *p_class) {
c.expression->set_datatype(expr);
DataType tmp;
- if (_get_member_type(p_class->base_type, E->key(), tmp)) {
- _set_error("The member \"" + String(E->key()) + "\" already exists in a parent class.", c.expression->line);
+ const StringName &constant_name = E->key();
+ if (constant_name == script_name || _get_member_type(p_class->base_type, constant_name, tmp)) {
+ _set_error("The member \"" + String(constant_name) + "\" already exists in a parent class.", c.expression->line);
return;
}
}
@@ -7679,7 +7693,7 @@ void GDScriptParser::_check_class_level_types(ClassNode *p_class) {
ClassNode::Member &v = p_class->variables.write[i];
DataType tmp;
- if (_get_member_type(p_class->base_type, v.identifier, tmp)) {
+ if (v.identifier == script_name || _get_member_type(p_class->base_type, v.identifier, tmp)) {
_set_error("The member \"" + String(v.identifier) + "\" already exists in a parent class.", v.line);
return;
}
@@ -7856,12 +7870,12 @@ void GDScriptParser::_check_function_types(FunctionNode *p_function) {
def_type.is_constant = false;
p_function->argument_types.write[i] = def_type;
} else {
- p_function->return_type = _resolve_type(p_function->return_type, p_function->line);
+ p_function->argument_types.write[i] = _resolve_type(p_function->argument_types[i], p_function->line);
if (!_is_type_compatible(p_function->argument_types[i], def_type, true)) {
String arg_name = p_function->arguments[i];
_set_error("Value type (" + def_type.to_string() + ") doesn't match the type of argument '" +
- arg_name + "' (" + p_function->arguments[i] + ").",
+ arg_name + "' (" + p_function->argument_types[i].to_string() + ").",
p_function->line);
}
}
@@ -8047,6 +8061,7 @@ void GDScriptParser::_check_block_types(BlockNode *p_block) {
last_var_assign = lv->assign;
if (lv->assign) {
+ lv->assign_op->arguments[0]->set_datatype(lv->datatype);
DataType assign_type = _reduce_node_type(lv->assign);
#ifdef DEBUG_ENABLED
if (assign_type.has_type && assign_type.kind == DataType::BUILTIN && assign_type.builtin_type == Variant::NIL) {
@@ -8191,11 +8206,12 @@ void GDScriptParser::_check_block_types(BlockNode *p_block) {
if (lh_type.has_type && rh_type.may_yield && op->arguments[1]->type == Node::TYPE_OPERATOR) {
_add_warning(GDScriptWarning::FUNCTION_MAY_YIELD, op->line, _find_function_name(static_cast<OperatorNode *>(op->arguments[1])));
}
-#endif // DEBUG_ENABLED
- bool type_match = check_types;
+#endif // DEBUG_ENABLED
+ bool type_match = lh_type.has_type && rh_type.has_type;
if (check_types && !_is_type_compatible(lh_type, rh_type)) {
type_match = false;
+
// Try supertype test
if (_is_type_compatible(rh_type, lh_type)) {
_mark_line_as_unsafe(op->line);
@@ -8266,7 +8282,11 @@ void GDScriptParser::_check_block_types(BlockNode *p_block) {
_mark_line_as_safe(op->line);
_reduce_node_type(op); // Test for safety anyway
#ifdef DEBUG_ENABLED
- _add_warning(GDScriptWarning::STANDALONE_EXPRESSION, statement->line);
+ if (op->op == OperatorNode::OP_TERNARY_IF) {
+ _add_warning(GDScriptWarning::STANDALONE_TERNARY, statement->line);
+ } else {
+ _add_warning(GDScriptWarning::STANDALONE_EXPRESSION, statement->line);
+ }
#endif // DEBUG_ENABLED
}
}
@@ -8483,11 +8503,8 @@ Error GDScriptParser::_parse(const String &p_base_path) {
current_class = main_class;
current_function = NULL;
current_block = NULL;
-#ifdef DEBUG_ENABLED
+
if (for_completion) check_types = false;
-#else
- check_types = false;
-#endif
// Resolve all class-level stuff before getting into function blocks
_check_class_level_types(main_class);
diff --git a/modules/gdscript/language_server/gdscript_extend_parser.cpp b/modules/gdscript/language_server/gdscript_extend_parser.cpp
index 8287c9c084..701809e755 100644
--- a/modules/gdscript/language_server/gdscript_extend_parser.cpp
+++ b/modules/gdscript/language_server/gdscript_extend_parser.cpp
@@ -112,9 +112,10 @@ void ExtendGDScriptParser::update_document_links(const String &p_code) {
FileAccessRef fs = FileAccess::create(FileAccess::ACCESS_RESOURCES);
tokenizer.set_code(p_code);
while (true) {
- if (tokenizer.get_token() == GDScriptTokenizer::TK_EOF) {
+ GDScriptTokenizerText::Token token = tokenizer.get_token();
+ if (token == GDScriptTokenizer::TK_EOF || token == GDScriptTokenizer::TK_ERROR) {
break;
- } else if (tokenizer.get_token() == GDScriptTokenizer::TK_CONSTANT) {
+ } else if (token == GDScriptTokenizer::TK_CONSTANT) {
const Variant &const_val = tokenizer.get_token_constant();
if (const_val.get_type() == Variant::STRING) {
String path = const_val;
@@ -522,6 +523,51 @@ const lsp::DocumentSymbol *ExtendGDScriptParser::search_symbol_defined_at_line(i
return ret;
}
+Error ExtendGDScriptParser::get_left_function_call(const lsp::Position &p_position, lsp::Position &r_func_pos, int &r_arg_index) const {
+
+ ERR_FAIL_INDEX_V(p_position.line, lines.size(), ERR_INVALID_PARAMETER);
+
+ int bracket_stack = 0;
+ int index = 0;
+
+ bool found = false;
+ for (int l = p_position.line; l >= 0; --l) {
+ String line = lines[l];
+ int c = line.length() - 1;
+ if (l == p_position.line) {
+ c = MIN(c, p_position.character - 1);
+ }
+
+ while (c >= 0) {
+ const CharType &character = line[c];
+ if (character == ')') {
+ ++bracket_stack;
+ } else if (character == '(') {
+ --bracket_stack;
+ if (bracket_stack < 0) {
+ found = true;
+ }
+ }
+ if (bracket_stack <= 0 && character == ',') {
+ ++index;
+ }
+ --c;
+ if (found) {
+ r_func_pos.character = c;
+ break;
+ }
+ }
+
+ if (found) {
+ r_func_pos.line = l;
+ r_arg_index = index;
+ return OK;
+ }
+ }
+
+ return ERR_METHOD_NOT_FOUND;
+}
+
const lsp::DocumentSymbol *ExtendGDScriptParser::get_symbol_defined_at_line(int p_line) const {
if (p_line <= 0) {
return &class_symbol;
diff --git a/modules/gdscript/language_server/gdscript_extend_parser.h b/modules/gdscript/language_server/gdscript_extend_parser.h
index 5afe991d24..43dfce994b 100644
--- a/modules/gdscript/language_server/gdscript_extend_parser.h
+++ b/modules/gdscript/language_server/gdscript_extend_parser.h
@@ -83,6 +83,8 @@ public:
_FORCE_INLINE_ const ClassMembers &get_members() const { return members; }
_FORCE_INLINE_ const HashMap<String, ClassMembers> &get_inner_classes() const { return inner_classes; }
+ Error get_left_function_call(const lsp::Position &p_position, lsp::Position &r_func_pos, int &r_arg_index) const;
+
String get_text_for_completion(const lsp::Position &p_cursor) const;
String get_text_for_lookup_symbol(const lsp::Position &p_cursor, const String &p_symbol = "", bool p_func_requred = false) const;
String get_identifier_under_position(const lsp::Position &p_position, Vector2i &p_offset) const;
diff --git a/modules/gdscript/language_server/gdscript_language_protocol.cpp b/modules/gdscript/language_server/gdscript_language_protocol.cpp
index cff7653d3a..7133c6b4be 100644
--- a/modules/gdscript/language_server/gdscript_language_protocol.cpp
+++ b/modules/gdscript/language_server/gdscript_language_protocol.cpp
@@ -156,7 +156,7 @@ void GDScriptLanguageProtocol::poll() {
server->poll();
}
-Error GDScriptLanguageProtocol::start(int p_port) {
+Error GDScriptLanguageProtocol::start(int p_port, const IP_Address &p_bind_ip) {
if (server == NULL) {
server = dynamic_cast<WebSocketServer *>(ClassDB::instance("WebSocketServer"));
ERR_FAIL_COND_V(!server, FAILED);
@@ -165,6 +165,7 @@ Error GDScriptLanguageProtocol::start(int p_port) {
server->connect("client_connected", this, "on_client_connected");
server->connect("client_disconnected", this, "on_client_disconnected");
}
+ server->set_bind_ip(p_bind_ip);
return server->listen(p_port);
}
diff --git a/modules/gdscript/language_server/gdscript_language_protocol.h b/modules/gdscript/language_server/gdscript_language_protocol.h
index e45db274e9..52c680ab19 100644
--- a/modules/gdscript/language_server/gdscript_language_protocol.h
+++ b/modules/gdscript/language_server/gdscript_language_protocol.h
@@ -77,7 +77,7 @@ public:
_FORCE_INLINE_ bool is_initialized() const { return _initialized; }
void poll();
- Error start(int p_port);
+ Error start(int p_port, const IP_Address &p_bind_ip);
void stop();
void notify_all_clients(const String &p_method, const Variant &p_params = Variant());
diff --git a/modules/gdscript/language_server/gdscript_language_server.cpp b/modules/gdscript/language_server/gdscript_language_server.cpp
index 159f2ba2d4..7170c63058 100644
--- a/modules/gdscript/language_server/gdscript_language_server.cpp
+++ b/modules/gdscript/language_server/gdscript_language_server.cpp
@@ -36,10 +36,15 @@
GDScriptLanguageServer::GDScriptLanguageServer() {
thread = NULL;
- thread_exit = false;
- _EDITOR_DEF("network/language_server/remote_port", 6008);
- _EDITOR_DEF("network/language_server/enable_smart_resolve", false);
+ 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);
+ _EDITOR_DEF("network/language_server/use_thread", use_thread);
}
void GDScriptLanguageServer::_notification(int p_what) {
@@ -51,12 +56,25 @@ void GDScriptLanguageServer::_notification(int p_what) {
case NOTIFICATION_EXIT_TREE:
stop();
break;
+ case NOTIFICATION_INTERNAL_PROCESS: {
+ if (started && !use_thread) {
+ protocol.poll();
+ }
+ } break;
+ case EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED: {
+ int port = (int)_EDITOR_GET("network/language_server/remote_port");
+ bool use_thread = (bool)_EDITOR_GET("network/language_server/use_thread");
+ if (port != this->port || use_thread != this->use_thread) {
+ this->stop();
+ this->start();
+ }
+ } break;
}
}
void GDScriptLanguageServer::thread_main(void *p_userdata) {
GDScriptLanguageServer *self = static_cast<GDScriptLanguageServer *>(p_userdata);
- while (!self->thread_exit) {
+ while (self->thread_running) {
// Poll 20 times per second
self->protocol.poll();
OS::get_singleton()->delay_usec(50000);
@@ -64,22 +82,30 @@ void GDScriptLanguageServer::thread_main(void *p_userdata) {
}
void GDScriptLanguageServer::start() {
- int port = (int)_EDITOR_GET("network/language_server/remote_port");
- if (protocol.start(port) == OK) {
+ port = (int)_EDITOR_GET("network/language_server/remote_port");
+ use_thread = (bool)_EDITOR_GET("network/language_server/use_thread");
+ if (protocol.start(port, IP_Address("127.0.0.1")) == OK) {
EditorNode::get_log()->add_message("--- GDScript language server started ---", EditorLog::MSG_TYPE_EDITOR);
- ERR_FAIL_COND(thread != NULL || thread_exit);
- thread_exit = false;
- thread = Thread::create(GDScriptLanguageServer::thread_main, this);
+ if (use_thread) {
+ ERR_FAIL_COND(thread != NULL);
+ thread_running = true;
+ thread = Thread::create(GDScriptLanguageServer::thread_main, this);
+ }
+ set_process_internal(!use_thread);
+ started = true;
}
}
void GDScriptLanguageServer::stop() {
- ERR_FAIL_COND(NULL == thread || thread_exit);
- thread_exit = true;
- Thread::wait_to_finish(thread);
- memdelete(thread);
- thread = NULL;
+ if (use_thread) {
+ ERR_FAIL_COND(NULL == thread);
+ thread_running = false;
+ Thread::wait_to_finish(thread);
+ memdelete(thread);
+ thread = NULL;
+ }
protocol.stop();
+ started = false;
EditorNode::get_log()->add_message("--- GDScript language server stopped ---", EditorLog::MSG_TYPE_EDITOR);
}
diff --git a/modules/gdscript/language_server/gdscript_language_server.h b/modules/gdscript/language_server/gdscript_language_server.h
index 191b8bfa85..228d29bf42 100644
--- a/modules/gdscript/language_server/gdscript_language_server.h
+++ b/modules/gdscript/language_server/gdscript_language_server.h
@@ -41,7 +41,10 @@ class GDScriptLanguageServer : public EditorPlugin {
GDScriptLanguageProtocol protocol;
Thread *thread;
- bool thread_exit;
+ bool thread_running;
+ bool started;
+ bool use_thread;
+ int port;
static void thread_main(void *p_userdata);
private:
diff --git a/modules/gdscript/language_server/gdscript_text_document.cpp b/modules/gdscript/language_server/gdscript_text_document.cpp
index 94cd2536e3..0572c5f746 100644
--- a/modules/gdscript/language_server/gdscript_text_document.cpp
+++ b/modules/gdscript/language_server/gdscript_text_document.cpp
@@ -49,6 +49,8 @@ void GDScriptTextDocument::_bind_methods() {
ClassDB::bind_method(D_METHOD("colorPresentation"), &GDScriptTextDocument::colorPresentation);
ClassDB::bind_method(D_METHOD("hover"), &GDScriptTextDocument::hover);
ClassDB::bind_method(D_METHOD("definition"), &GDScriptTextDocument::definition);
+ ClassDB::bind_method(D_METHOD("declaration"), &GDScriptTextDocument::declaration);
+ ClassDB::bind_method(D_METHOD("signatureHelp"), &GDScriptTextDocument::signatureHelp);
ClassDB::bind_method(D_METHOD("show_native_symbol_in_editor"), &GDScriptTextDocument::show_native_symbol_in_editor);
}
@@ -267,7 +269,7 @@ Dictionary GDScriptTextDocument::resolve(const Dictionary &p_params) {
if ((item.kind == lsp::CompletionItemKind::Method || item.kind == lsp::CompletionItemKind::Function) && !item.label.ends_with("):")) {
item.insertText = item.label + "(";
- if (symbol && symbol->detail.find(",") == -1) {
+ if (symbol && symbol->children.empty()) {
item.insertText += ")";
}
} else if (item.kind == lsp::CompletionItemKind::Event) {
@@ -340,68 +342,64 @@ Variant GDScriptTextDocument::hover(const Dictionary &p_params) {
}
Array GDScriptTextDocument::definition(const Dictionary &p_params) {
- Array arr;
-
lsp::TextDocumentPositionParams params;
params.load(p_params);
+ List<const lsp::DocumentSymbol *> symbols;
+ Array arr = this->find_symbols(params, symbols);
+ return arr;
+}
- const lsp::DocumentSymbol *symbol = GDScriptLanguageProtocol::get_singleton()->get_workspace()->resolve_symbol(params);
- if (symbol) {
- lsp::Location location;
- location.uri = symbol->uri;
- location.range = symbol->range;
-
- const String &path = GDScriptLanguageProtocol::get_singleton()->get_workspace()->get_file_path(symbol->uri);
- if (file_checker->file_exists(path)) {
- arr.push_back(location.to_json());
- } else if (!symbol->native_class.empty()) {
- if (GDScriptLanguageProtocol::get_singleton()->is_goto_native_symbols_enabled()) {
- String id;
- switch (symbol->kind) {
- case lsp::SymbolKind::Class:
- id = "class_name:" + symbol->name;
- break;
- case lsp::SymbolKind::Constant:
- id = "class_constant:" + symbol->native_class + ":" + symbol->name;
- break;
- case lsp::SymbolKind::Property:
- case lsp::SymbolKind::Variable:
- id = "class_property:" + symbol->native_class + ":" + symbol->name;
- break;
- case lsp::SymbolKind::Enum:
- id = "class_enum:" + symbol->native_class + ":" + symbol->name;
- break;
- case lsp::SymbolKind::Method:
- case lsp::SymbolKind::Function:
- id = "class_method:" + symbol->native_class + ":" + symbol->name;
- break;
- default:
- id = "class_global:" + symbol->native_class + ":" + symbol->name;
- break;
- }
- call_deferred("show_native_symbol_in_editor", id);
- } else {
- notify_client_show_symbol(symbol);
+Variant GDScriptTextDocument::declaration(const Dictionary &p_params) {
+ lsp::TextDocumentPositionParams params;
+ params.load(p_params);
+ List<const lsp::DocumentSymbol *> symbols;
+ Array arr = this->find_symbols(params, symbols);
+ if (arr.empty() && !symbols.empty() && !symbols.front()->get()->native_class.empty()) { // Find a native symbol
+ const lsp::DocumentSymbol *symbol = symbols.front()->get();
+ if (GDScriptLanguageProtocol::get_singleton()->is_goto_native_symbols_enabled()) {
+ String id;
+ switch (symbol->kind) {
+ case lsp::SymbolKind::Class:
+ id = "class_name:" + symbol->name;
+ break;
+ case lsp::SymbolKind::Constant:
+ id = "class_constant:" + symbol->native_class + ":" + symbol->name;
+ break;
+ case lsp::SymbolKind::Property:
+ case lsp::SymbolKind::Variable:
+ id = "class_property:" + symbol->native_class + ":" + symbol->name;
+ break;
+ case lsp::SymbolKind::Enum:
+ id = "class_enum:" + symbol->native_class + ":" + symbol->name;
+ break;
+ case lsp::SymbolKind::Method:
+ case lsp::SymbolKind::Function:
+ id = "class_method:" + symbol->native_class + ":" + symbol->name;
+ break;
+ default:
+ id = "class_global:" + symbol->native_class + ":" + symbol->name;
+ break;
}
+ call_deferred("show_native_symbol_in_editor", id);
+ } else {
+ notify_client_show_symbol(symbol);
}
- } else if (GDScriptLanguageProtocol::get_singleton()->is_smart_resolve_enabled()) {
+ }
+ return arr;
+}
- List<const lsp::DocumentSymbol *> list;
- GDScriptLanguageProtocol::get_singleton()->get_workspace()->resolve_related_symbols(params, list);
- for (List<const lsp::DocumentSymbol *>::Element *E = list.front(); E; E = E->next()) {
+Variant GDScriptTextDocument::signatureHelp(const Dictionary &p_params) {
+ Variant ret;
- if (const lsp::DocumentSymbol *s = E->get()) {
- if (!s->uri.empty()) {
- lsp::Location location;
- location.uri = s->uri;
- location.range = s->range;
- arr.push_back(location.to_json());
- }
- }
- }
+ lsp::TextDocumentPositionParams params;
+ params.load(p_params);
+
+ lsp::SignatureHelp s;
+ if (OK == GDScriptLanguageProtocol::get_singleton()->get_workspace()->resolve_signature(params, s)) {
+ ret = s.to_json();
}
- return arr;
+ return ret;
}
GDScriptTextDocument::GDScriptTextDocument() {
@@ -421,3 +419,33 @@ void GDScriptTextDocument::show_native_symbol_in_editor(const String &p_symbol_i
ScriptEditor::get_singleton()->call_deferred("_help_class_goto", p_symbol_id);
OS::get_singleton()->move_window_to_foreground();
}
+
+Array GDScriptTextDocument::find_symbols(const lsp::TextDocumentPositionParams &p_location, List<const lsp::DocumentSymbol *> &r_list) {
+ Array arr;
+ const lsp::DocumentSymbol *symbol = GDScriptLanguageProtocol::get_singleton()->get_workspace()->resolve_symbol(p_location);
+ if (symbol) {
+ lsp::Location location;
+ location.uri = symbol->uri;
+ location.range = symbol->range;
+ const String &path = GDScriptLanguageProtocol::get_singleton()->get_workspace()->get_file_path(symbol->uri);
+ if (file_checker->file_exists(path)) {
+ arr.push_back(location.to_json());
+ }
+ r_list.push_back(symbol);
+ } else if (GDScriptLanguageProtocol::get_singleton()->is_smart_resolve_enabled()) {
+ List<const lsp::DocumentSymbol *> list;
+ GDScriptLanguageProtocol::get_singleton()->get_workspace()->resolve_related_symbols(p_location, list);
+ for (List<const lsp::DocumentSymbol *>::Element *E = list.front(); E; E = E->next()) {
+ if (const lsp::DocumentSymbol *s = E->get()) {
+ if (!s->uri.empty()) {
+ lsp::Location location;
+ location.uri = s->uri;
+ location.range = s->range;
+ arr.push_back(location.to_json());
+ r_list.push_back(s);
+ }
+ }
+ }
+ }
+ return arr;
+}
diff --git a/modules/gdscript/language_server/gdscript_text_document.h b/modules/gdscript/language_server/gdscript_text_document.h
index 8a7c6fb98c..b2fd0c31f9 100644
--- a/modules/gdscript/language_server/gdscript_text_document.h
+++ b/modules/gdscript/language_server/gdscript_text_document.h
@@ -51,6 +51,7 @@ protected:
Array native_member_completions;
private:
+ Array find_symbols(const lsp::TextDocumentPositionParams &p_location, List<const lsp::DocumentSymbol *> &r_list);
lsp::TextDocumentItem load_document_item(const Variant &p_param);
void notify_client_show_symbol(const lsp::DocumentSymbol *symbol);
@@ -65,6 +66,8 @@ public:
Array colorPresentation(const Dictionary &p_params);
Variant hover(const Dictionary &p_params);
Array definition(const Dictionary &p_params);
+ Variant declaration(const Dictionary &p_params);
+ Variant signatureHelp(const Dictionary &p_params);
void initialize();
diff --git a/modules/gdscript/language_server/gdscript_workspace.cpp b/modules/gdscript/language_server/gdscript_workspace.cpp
index 0661c4af26..1c0590cff1 100644
--- a/modules/gdscript/language_server/gdscript_workspace.cpp
+++ b/modules/gdscript/language_server/gdscript_workspace.cpp
@@ -252,6 +252,12 @@ Error GDScriptWorkspace::initialize() {
bool arg_default_value_started = false;
for (int j = 0; j < data.arguments.size(); j++) {
const DocData::ArgumentDoc &arg = data.arguments[j];
+
+ lsp::DocumentSymbol symbol_arg;
+ symbol_arg.name = arg.name;
+ symbol_arg.kind = lsp::SymbolKind::Variable;
+ symbol_arg.detail = arg.type;
+
if (!arg_default_value_started && !arg.default_value.empty()) {
arg_default_value_started = true;
}
@@ -263,6 +269,8 @@ Error GDScriptWorkspace::initialize() {
arg_str += ", ";
}
params += arg_str;
+
+ symbol.children.push_back(symbol_arg);
}
if (data.qualifiers.find("vararg") != -1) {
params += params.empty() ? "..." : ", ...";
@@ -513,6 +521,49 @@ Dictionary GDScriptWorkspace::generate_script_api(const String &p_path) {
return api;
}
+Error GDScriptWorkspace::resolve_signature(const lsp::TextDocumentPositionParams &p_doc_pos, lsp::SignatureHelp &r_signature) {
+ if (const ExtendGDScriptParser *parser = get_parse_result(get_file_path(p_doc_pos.textDocument.uri))) {
+
+ lsp::TextDocumentPositionParams text_pos;
+ text_pos.textDocument = p_doc_pos.textDocument;
+
+ if (parser->get_left_function_call(p_doc_pos.position, text_pos.position, r_signature.activeParameter) == OK) {
+
+ List<const lsp::DocumentSymbol *> symbols;
+
+ if (const lsp::DocumentSymbol *symbol = resolve_symbol(text_pos)) {
+ symbols.push_back(symbol);
+ } else if (GDScriptLanguageProtocol::get_singleton()->is_smart_resolve_enabled()) {
+ GDScriptLanguageProtocol::get_singleton()->get_workspace()->resolve_related_symbols(text_pos, symbols);
+ }
+
+ for (List<const lsp::DocumentSymbol *>::Element *E = symbols.front(); E; E = E->next()) {
+ const lsp::DocumentSymbol *symbol = E->get();
+ if (symbol->kind == lsp::SymbolKind::Method || symbol->kind == lsp::SymbolKind::Function) {
+
+ lsp::SignatureInformation signature_info;
+ signature_info.label = symbol->detail;
+ signature_info.documentation = symbol->render();
+
+ for (int i = 0; i < symbol->children.size(); i++) {
+ const lsp::DocumentSymbol &arg = symbol->children[i];
+ lsp::ParameterInformation arg_info;
+ arg_info.label = arg.name;
+ signature_info.parameters.push_back(arg_info);
+ }
+ r_signature.signatures.push_back(signature_info);
+ break;
+ }
+ }
+
+ if (r_signature.signatures.size()) {
+ return OK;
+ }
+ }
+ }
+ return ERR_METHOD_NOT_FOUND;
+}
+
GDScriptWorkspace::GDScriptWorkspace() {
ProjectSettings::get_singleton()->get_resource_path();
}
diff --git a/modules/gdscript/language_server/gdscript_workspace.h b/modules/gdscript/language_server/gdscript_workspace.h
index f44153dcd0..146a5cb7c9 100644
--- a/modules/gdscript/language_server/gdscript_workspace.h
+++ b/modules/gdscript/language_server/gdscript_workspace.h
@@ -83,6 +83,7 @@ public:
const lsp::DocumentSymbol *resolve_native_symbol(const lsp::NativeSymbolInspectParams &p_params);
void resolve_document_links(const String &p_uri, List<lsp::DocumentLink> &r_list);
Dictionary generate_script_api(const String &p_path);
+ Error resolve_signature(const lsp::TextDocumentPositionParams &p_doc_pos, lsp::SignatureHelp &r_signature);
GDScriptWorkspace();
~GDScriptWorkspace();
diff --git a/modules/gdscript/language_server/lsp.hpp b/modules/gdscript/language_server/lsp.hpp
index ffeea70008..a2dcc48820 100644
--- a/modules/gdscript/language_server/lsp.hpp
+++ b/modules/gdscript/language_server/lsp.hpp
@@ -330,8 +330,6 @@ struct CompletionOptions {
triggerCharacters.push_back("$");
triggerCharacters.push_back("'");
triggerCharacters.push_back("\"");
- triggerCharacters.push_back("(");
- triggerCharacters.push_back(",");
}
Dictionary to_json() const {
@@ -1402,6 +1400,120 @@ struct Hover {
}
};
+/**
+ * Represents a parameter of a callable-signature. A parameter can
+ * have a label and a doc-comment.
+ */
+struct ParameterInformation {
+
+ /**
+ * The label of this parameter information.
+ *
+ * Either a string or an inclusive start and exclusive end offsets within its containing
+ * signature label. (see SignatureInformation.label). The offsets are based on a UTF-16
+ * string representation as `Position` and `Range` does.
+ *
+ * *Note*: a label of type string should be a substring of its containing signature label.
+ * Its intended use case is to highlight the parameter label part in the `SignatureInformation.label`.
+ */
+ String label;
+
+ /**
+ * The human-readable doc-comment of this parameter. Will be shown
+ * in the UI but can be omitted.
+ */
+ MarkupContent documentation;
+
+ Dictionary to_json() const {
+ Dictionary dict;
+ dict["label"] = label;
+ dict["documentation"] = documentation.to_json();
+ return dict;
+ }
+};
+
+/**
+ * Represents the signature of something callable. A signature
+ * can have a label, like a function-name, a doc-comment, and
+ * a set of parameters.
+ */
+struct SignatureInformation {
+ /**
+ * The label of this signature. Will be shown in
+ * the UI.
+ */
+ String label;
+
+ /**
+ * The human-readable doc-comment of this signature. Will be shown
+ * in the UI but can be omitted.
+ */
+ MarkupContent documentation;
+
+ /**
+ * The parameters of this signature.
+ */
+ Vector<ParameterInformation> parameters;
+
+ Dictionary to_json() const {
+ Dictionary dict;
+ dict["label"] = label;
+ dict["documentation"] = documentation.to_json();
+ Array args;
+ for (int i = 0; i < parameters.size(); i++) {
+ args.push_back(parameters[i].to_json());
+ }
+ dict["parameters"] = args;
+ return dict;
+ }
+};
+
+/**
+ * Signature help represents the signature of something
+ * callable. There can be multiple signature but only one
+ * active and only one active parameter.
+ */
+struct SignatureHelp {
+ /**
+ * One or more signatures.
+ */
+ Vector<SignatureInformation> signatures;
+
+ /**
+ * The active signature. If omitted or the value lies outside the
+ * range of `signatures` the value defaults to zero or is ignored if
+ * `signatures.length === 0`. Whenever possible implementors should
+ * make an active decision about the active signature and shouldn't
+ * rely on a default value.
+ * In future version of the protocol this property might become
+ * mandatory to better express this.
+ */
+ int activeSignature = 0;
+
+ /**
+ * The active parameter of the active signature. If omitted or the value
+ * lies outside the range of `signatures[activeSignature].parameters`
+ * defaults to 0 if the active signature has parameters. If
+ * the active signature has no parameters it is ignored.
+ * In future version of the protocol this property might become
+ * mandatory to better express the active parameter if the
+ * active signature does have any.
+ */
+ int activeParameter = 0;
+
+ Dictionary to_json() const {
+ Dictionary dict;
+ Array sigs;
+ for (int i = 0; i < signatures.size(); i++) {
+ sigs.push_back(signatures[i].to_json());
+ }
+ dict["signatures"] = sigs;
+ dict["activeSignature"] = activeSignature;
+ dict["activeParameter"] = activeParameter;
+ return dict;
+ }
+};
+
struct ServerCapabilities {
/**
* Defines how text documents are synced. Is either a detailed structure defining each notification or
@@ -1532,6 +1644,8 @@ struct ServerCapabilities {
Dictionary dict;
dict["textDocumentSync"] = (int)textDocumentSync.change;
dict["completionProvider"] = completionProvider.to_json();
+ signatureHelpProvider.triggerCharacters.push_back(",");
+ signatureHelpProvider.triggerCharacters.push_back("(");
dict["signatureHelpProvider"] = signatureHelpProvider.to_json();
dict["codeLensProvider"] = false; // codeLensProvider.to_json();
dict["documentOnTypeFormattingProvider"] = documentOnTypeFormattingProvider.to_json();
diff --git a/modules/gridmap/grid_map.cpp b/modules/gridmap/grid_map.cpp
index 8126c9338f..3d40220869 100644
--- a/modules/gridmap/grid_map.cpp
+++ b/modules/gridmap/grid_map.cpp
@@ -122,7 +122,7 @@ bool GridMap::_get(const StringName &p_name, Variant &r_ret) const {
Array ret;
ret.resize(baked_meshes.size());
for (int i = 0; i < baked_meshes.size(); i++) {
- ret.push_back(baked_meshes[i].mesh);
+ ret[i] = baked_meshes[i].mesh;
}
r_ret = ret;
diff --git a/modules/mono/csharp_script.cpp b/modules/mono/csharp_script.cpp
index d82e78d080..0f6b8357b8 100644
--- a/modules/mono/csharp_script.cpp
+++ b/modules/mono/csharp_script.cpp
@@ -159,6 +159,19 @@ void CSharpLanguage::finish() {
// Clear here, after finalizing all domains to make sure there is nothing else referencing the elements.
script_bindings.clear();
+#ifdef DEBUG_ENABLED
+ for (List<ObjectID>::Element *E = unsafely_referenced_objects.front(); E; E = E->next()) {
+ const ObjectID &id = E->get();
+ Object *obj = ObjectDB::get_instance(id);
+
+ if (obj) {
+ ERR_PRINTS("Leaked unsafe reference to object: " + obj->get_class() + ":" + itos(id));
+ } else {
+ ERR_PRINTS("Leaked unsafe reference to deleted object: " + itos(id));
+ }
+ }
+#endif
+
finalizing = false;
}
@@ -546,6 +559,7 @@ Vector<ScriptLanguage::StackInfo> CSharpLanguage::debug_get_current_stack_info()
#ifdef DEBUG_ENABLED
_TLS_RECURSION_GUARD_V_(Vector<StackInfo>());
+ GD_MONO_SCOPE_THREAD_ATTACH;
if (!gdmono->is_runtime_initialized() || !GDMono::get_singleton()->get_core_api_assembly() || !GDMonoCache::cached_data.corlib_cache_updated)
return Vector<StackInfo>();
@@ -570,6 +584,7 @@ Vector<ScriptLanguage::StackInfo> CSharpLanguage::debug_get_current_stack_info()
Vector<ScriptLanguage::StackInfo> CSharpLanguage::stack_trace_get_info(MonoObject *p_stack_trace) {
_TLS_RECURSION_GUARD_V_(Vector<StackInfo>());
+ GD_MONO_SCOPE_THREAD_ATTACH;
MonoException *exc = NULL;
@@ -615,6 +630,23 @@ Vector<ScriptLanguage::StackInfo> CSharpLanguage::stack_trace_get_info(MonoObjec
}
#endif
+void CSharpLanguage::post_unsafe_reference(Object *p_obj) {
+#ifdef DEBUG_ENABLED
+ ObjectID id = p_obj->get_instance_id();
+ ERR_FAIL_COND_MSG(unsafely_referenced_objects.find(id), "Multiple unsafe references for object: " + p_obj->get_class() + ":" + itos(id));
+ unsafely_referenced_objects.push_back(id);
+#endif
+}
+
+void CSharpLanguage::pre_unsafe_unreference(Object *p_obj) {
+#ifdef DEBUG_ENABLED
+ ObjectID id = p_obj->get_instance_id();
+ List<ObjectID>::Element *elem = unsafely_referenced_objects.find(id);
+ ERR_FAIL_NULL(elem);
+ unsafely_referenced_objects.erase(elem);
+#endif
+}
+
void CSharpLanguage::frame() {
if (gdmono && gdmono->is_runtime_initialized() && gdmono->get_core_api_assembly() != NULL) {
@@ -659,6 +691,7 @@ void CSharpLanguage::reload_all_scripts() {
#ifdef GD_MONO_HOT_RELOAD
if (is_assembly_reloading_needed()) {
+ GD_MONO_SCOPE_THREAD_ATTACH;
reload_assemblies(false);
}
#endif
@@ -676,6 +709,7 @@ void CSharpLanguage::reload_tool_script(const Ref<Script> &p_script, bool p_soft
#ifdef GD_MONO_HOT_RELOAD
if (is_assembly_reloading_needed()) {
+ GD_MONO_SCOPE_THREAD_ATTACH;
reload_assemblies(p_soft_reload);
}
#endif
@@ -1286,6 +1320,7 @@ bool CSharpLanguage::setup_csharp_script_binding(CSharpScriptBinding &r_script_b
// See: godot_icall_Reference_Dtor(MonoObject *p_obj, Object *p_ptr)
ref->reference();
+ CSharpLanguage::get_singleton()->post_unsafe_reference(ref);
}
return true;
@@ -1325,6 +1360,8 @@ void CSharpLanguage::free_instance_binding_data(void *p_data) {
if (finalizing)
return; // inside CSharpLanguage::finish(), all the gchandle bindings are released there
+ GD_MONO_ASSERT_THREAD_ATTACHED;
+
{
SCOPED_MUTEX_LOCK(language_bind_mutex);
@@ -1351,6 +1388,7 @@ void CSharpLanguage::refcount_incremented_instance_binding(Object *p_object) {
#ifdef DEBUG_ENABLED
CRASH_COND(!ref_owner);
+ CRASH_COND(!p_object->has_script_instance_binding(get_language_index()));
#endif
void *data = p_object->get_script_instance_binding(get_language_index());
@@ -1363,6 +1401,8 @@ void CSharpLanguage::refcount_incremented_instance_binding(Object *p_object) {
return;
if (ref_owner->reference_get_count() > 1 && gchandle->is_weak()) { // The managed side also holds a reference, hence 1 instead of 0
+ GD_MONO_SCOPE_THREAD_ATTACH;
+
// The reference count was increased after the managed side was the only one referencing our owner.
// This means the owner is being referenced again by the unmanaged side,
// so the owner must hold the managed side alive again to avoid it from being GCed.
@@ -1384,6 +1424,7 @@ bool CSharpLanguage::refcount_decremented_instance_binding(Object *p_object) {
#ifdef DEBUG_ENABLED
CRASH_COND(!ref_owner);
+ CRASH_COND(!p_object->has_script_instance_binding(get_language_index()));
#endif
void *data = p_object->get_script_instance_binding(get_language_index());
@@ -1398,6 +1439,8 @@ bool CSharpLanguage::refcount_decremented_instance_binding(Object *p_object) {
return refcount == 0;
if (refcount == 1 && gchandle.is_valid() && !gchandle->is_weak()) { // The managed side also holds a reference, hence 1 instead of 0
+ GD_MONO_SCOPE_THREAD_ATTACH;
+
// If owner owner is no longer referenced by the unmanaged side,
// the managed instance takes responsibility of deleting the owner when GCed.
@@ -1449,6 +1492,8 @@ bool CSharpInstance::set(const StringName &p_name, const Variant &p_value) {
ERR_FAIL_COND_V(!script.is_valid(), false);
+ GD_MONO_SCOPE_THREAD_ATTACH;
+
MonoObject *mono_object = get_mono_object();
ERR_FAIL_NULL_V(mono_object, false);
@@ -1501,6 +1546,8 @@ bool CSharpInstance::get(const StringName &p_name, Variant &r_ret) const {
ERR_FAIL_COND_V(!script.is_valid(), false);
+ GD_MONO_SCOPE_THREAD_ATTACH;
+
MonoObject *mono_object = get_mono_object();
ERR_FAIL_NULL_V(mono_object, false);
@@ -1594,6 +1641,8 @@ void CSharpInstance::get_property_list(List<PropertyInfo> *p_properties) const {
ERR_FAIL_COND(!script.is_valid());
+ GD_MONO_SCOPE_THREAD_ATTACH;
+
MonoObject *mono_object = get_mono_object();
ERR_FAIL_NULL(mono_object);
@@ -1638,6 +1687,8 @@ bool CSharpInstance::has_method(const StringName &p_method) const {
if (!script.is_valid())
return false;
+ GD_MONO_SCOPE_THREAD_ATTACH;
+
GDMonoClass *top = script->script_class;
while (top && top != script->native) {
@@ -1653,6 +1704,11 @@ bool CSharpInstance::has_method(const StringName &p_method) const {
Variant CSharpInstance::call(const StringName &p_method, const Variant **p_args, int p_argcount, Variant::CallError &r_error) {
+ if (!script.is_valid())
+ ERR_FAIL_V(Variant());
+
+ GD_MONO_SCOPE_THREAD_ATTACH;
+
MonoObject *mono_object = get_mono_object();
if (!mono_object) {
@@ -1660,9 +1716,6 @@ Variant CSharpInstance::call(const StringName &p_method, const Variant **p_args,
ERR_FAIL_V(Variant());
}
- if (!script.is_valid())
- ERR_FAIL_V(Variant());
-
GDMonoClass *top = script->script_class;
while (top && top != script->native) {
@@ -1690,6 +1743,8 @@ Variant CSharpInstance::call(const StringName &p_method, const Variant **p_args,
void CSharpInstance::call_multilevel(const StringName &p_method, const Variant **p_args, int p_argcount) {
+ GD_MONO_SCOPE_THREAD_ATTACH;
+
if (script.is_valid()) {
MonoObject *mono_object = get_mono_object();
@@ -1701,6 +1756,8 @@ void CSharpInstance::call_multilevel(const StringName &p_method, const Variant *
void CSharpInstance::_call_multilevel(MonoObject *p_mono_object, const StringName &p_method, const Variant **p_args, int p_argcount) {
+ GD_MONO_ASSERT_THREAD_ATTACHED;
+
GDMonoClass *top = script->script_class;
while (top && top != script->native) {
@@ -1736,9 +1793,12 @@ bool CSharpInstance::_reference_owner_unsafe() {
// See: _unreference_owner_unsafe()
// May not me referenced yet, so we must use init_ref() instead of reference()
- bool success = Object::cast_to<Reference>(owner)->init_ref();
- unsafe_referenced = success;
- return success;
+ if (static_cast<Reference *>(owner)->init_ref()) {
+ CSharpLanguage::get_singleton()->post_unsafe_reference(owner);
+ unsafe_referenced = true;
+ }
+
+ return unsafe_referenced;
}
bool CSharpInstance::_unreference_owner_unsafe() {
@@ -1759,6 +1819,7 @@ bool CSharpInstance::_unreference_owner_unsafe() {
// See: _reference_owner_unsafe()
// Destroying the owner here means self destructing, so we defer the owner destruction to the caller.
+ CSharpLanguage::get_singleton()->pre_unsafe_unreference(owner);
return static_cast<Reference *>(owner)->unreference();
}
@@ -1859,6 +1920,8 @@ void CSharpInstance::refcount_incremented() {
Reference *ref_owner = Object::cast_to<Reference>(owner);
if (ref_owner->reference_get_count() > 1 && gchandle->is_weak()) { // The managed side also holds a reference, hence 1 instead of 0
+ GD_MONO_SCOPE_THREAD_ATTACH;
+
// The reference count was increased after the managed side was the only one referencing our owner.
// This means the owner is being referenced again by the unmanaged side,
// so the owner must hold the managed side alive again to avoid it from being GCed.
@@ -1882,6 +1945,8 @@ bool CSharpInstance::refcount_decremented() {
int refcount = ref_owner->reference_get_count();
if (refcount == 1 && !gchandle->is_weak()) { // The managed side also holds a reference, hence 1 instead of 0
+ GD_MONO_SCOPE_THREAD_ATTACH;
+
// If owner owner is no longer referenced by the unmanaged side,
// the managed instance takes responsibility of deleting the owner when GCed.
@@ -1922,6 +1987,8 @@ MultiplayerAPI::RPCMode CSharpInstance::_member_get_rpc_mode(IMonoClassMember *p
MultiplayerAPI::RPCMode CSharpInstance::get_rpc_mode(const StringName &p_method) const {
+ GD_MONO_SCOPE_THREAD_ATTACH;
+
GDMonoClass *top = script->script_class;
while (top && top != script->native) {
@@ -1938,6 +2005,8 @@ MultiplayerAPI::RPCMode CSharpInstance::get_rpc_mode(const StringName &p_method)
MultiplayerAPI::RPCMode CSharpInstance::get_rset_mode(const StringName &p_variable) const {
+ GD_MONO_SCOPE_THREAD_ATTACH;
+
GDMonoClass *top = script->script_class;
while (top && top != script->native) {
@@ -1959,6 +2028,8 @@ MultiplayerAPI::RPCMode CSharpInstance::get_rset_mode(const StringName &p_variab
void CSharpInstance::notification(int p_notification) {
+ GD_MONO_SCOPE_THREAD_ATTACH;
+
if (p_notification == Object::NOTIFICATION_PREDELETE) {
// When NOTIFICATION_PREDELETE is sent, we also take the chance to call Dispose().
// It's safe to call Dispose() multiple times and NOTIFICATION_PREDELETE is guaranteed
@@ -1996,6 +2067,8 @@ void CSharpInstance::notification(int p_notification) {
void CSharpInstance::_call_notification(int p_notification) {
+ GD_MONO_ASSERT_THREAD_ATTACHED;
+
MonoObject *mono_object = get_mono_object();
ERR_FAIL_NULL(mono_object);
@@ -2020,6 +2093,8 @@ void CSharpInstance::_call_notification(int p_notification) {
}
String CSharpInstance::to_string(bool *r_valid) {
+ GD_MONO_SCOPE_THREAD_ATTACH;
+
MonoObject *mono_object = get_mono_object();
if (mono_object == NULL) {
@@ -2068,6 +2143,8 @@ CSharpInstance::CSharpInstance() :
CSharpInstance::~CSharpInstance() {
+ GD_MONO_SCOPE_THREAD_ATTACH;
+
destructing_script_instance = true;
if (gchandle.is_valid()) {
@@ -2099,6 +2176,17 @@ CSharpInstance::~CSharpInstance() {
// Transfer ownership to an "instance binding"
+ Reference *ref_owner = static_cast<Reference *>(owner);
+
+ // We will unreference the owner before referencing it again, so we need to keep it alive
+ Ref<Reference> scope_keep_owner_alive(ref_owner);
+ (void)scope_keep_owner_alive;
+
+ // Unreference the owner here, before the new "instance binding" references it.
+ // Otherwise, the unsafe reference debug checks will incorrectly detect a bug.
+ bool die = _unreference_owner_unsafe();
+ CRASH_COND(die == true); // `owner_keep_alive` holds a reference, so it can't die
+
void *data = owner->get_script_instance_binding(CSharpLanguage::get_singleton()->get_language_index());
CRASH_COND(data == NULL);
@@ -2114,8 +2202,10 @@ CSharpInstance::~CSharpInstance() {
}
}
- bool die = _unreference_owner_unsafe();
- CRASH_COND(die == true); // The "instance binding" should be holding a reference
+#ifdef DEBUG_ENABLED
+ // The "instance binding" holds a reference so the refcount should be at least 2 before `scope_keep_owner_alive` goes out of scope
+ CRASH_COND(ref_owner->reference_get_count() <= 1);
+#endif
}
if (script.is_valid() && owner) {
@@ -2158,6 +2248,8 @@ void CSharpScript::_update_exports_values(Map<StringName, Variant> &values, List
void CSharpScript::_update_member_info_no_exports() {
if (exports_invalidated) {
+ GD_MONO_ASSERT_THREAD_ATTACHED;
+
exports_invalidated = false;
member_info.clear();
@@ -2216,6 +2308,8 @@ bool CSharpScript::_update_exports() {
bool changed = false;
if (exports_invalidated) {
+ GD_MONO_SCOPE_THREAD_ATTACH;
+
exports_invalidated = false;
changed = true;
@@ -2243,7 +2337,11 @@ bool CSharpScript::_update_exports() {
MonoException *ctor_exc = NULL;
ctor->invoke(tmp_object, NULL, &ctor_exc);
+ Object *tmp_native = GDMonoMarshal::unbox<Object *>(CACHED_FIELD(GodotObject, ptr)->get_value(tmp_object));
+
if (ctor_exc) {
+ // TODO: Should we free 'tmp_native' if the exception was thrown after its creation?
+
MonoGCHandle::free_handle(tmp_pinned_gchandle);
tmp_object = NULL;
@@ -2322,6 +2420,15 @@ bool CSharpScript::_update_exports() {
MonoGCHandle::free_handle(tmp_pinned_gchandle);
tmp_object = NULL;
+
+ if (tmp_native && !Object::cast_to<Reference>(tmp_native)) {
+ Node *node = Object::cast_to<Node>(tmp_native);
+ if (node && node->is_inside_tree()) {
+ ERR_PRINTS("Temporary instance was added to the scene tree.");
+ } else {
+ memdelete(tmp_native);
+ }
+ }
}
placeholder_fallback_enabled = false;
@@ -2352,6 +2459,8 @@ void CSharpScript::load_script_signals(GDMonoClass *p_class, GDMonoClass *p_nati
// make sure this classes signals are empty when loading for the first time
_signals.clear();
+ GD_MONO_SCOPE_THREAD_ATTACH;
+
GDMonoClass *top = p_class;
while (top && top != p_native_class) {
const Vector<GDMonoClass *> &delegates = top->get_all_delegates();
@@ -2372,6 +2481,8 @@ void CSharpScript::load_script_signals(GDMonoClass *p_class, GDMonoClass *p_nati
}
bool CSharpScript::_get_signal(GDMonoClass *p_class, GDMonoClass *p_delegate, Vector<Argument> &params) {
+ GD_MONO_ASSERT_THREAD_ATTACHED;
+
if (p_delegate->has_attribute(CACHED_CLASS(SignalAttribute))) {
MonoType *raw_type = p_delegate->get_mono_type();
@@ -2413,6 +2524,8 @@ bool CSharpScript::_get_signal(GDMonoClass *p_class, GDMonoClass *p_delegate, Ve
*/
bool CSharpScript::_get_member_export(IMonoClassMember *p_member, bool p_inspect_export, PropertyInfo &r_prop_info, bool &r_exported) {
+ GD_MONO_ASSERT_THREAD_ATTACHED;
+
// Goddammit, C++. All I wanted was some nested functions.
#define MEMBER_FULL_QUALIFIED_NAME(m_member) \
(m_member->get_enclosing_class()->get_full_name() + "." + (String)m_member->get_name())
@@ -2491,6 +2604,8 @@ bool CSharpScript::_get_member_export(IMonoClassMember *p_member, bool p_inspect
int CSharpScript::_try_get_member_export_hint(IMonoClassMember *p_member, ManagedType p_type, Variant::Type p_variant_type, bool p_allow_generics, PropertyHint &r_hint, String &r_hint_string) {
+ GD_MONO_ASSERT_THREAD_ATTACHED;
+
if (p_variant_type == Variant::INT && p_type.type_encoding == MONO_TYPE_VALUETYPE && mono_class_is_enum(p_type.type_class->get_mono_ptr())) {
r_hint = PROPERTY_HINT_ENUM;
@@ -2600,6 +2715,8 @@ Variant CSharpScript::call(const StringName &p_method, const Variant **p_args, i
return Variant();
}
+ GD_MONO_SCOPE_THREAD_ATTACH;
+
GDMonoClass *top = script_class;
while (top && top != native) {
@@ -2792,6 +2909,8 @@ StringName CSharpScript::get_instance_base_type() const {
CSharpInstance *CSharpScript::_create_instance(const Variant **p_args, int p_argcount, Object *p_owner, bool p_isref, Variant::CallError &r_error) {
+ GD_MONO_ASSERT_THREAD_ATTACHED;
+
/* STEP 1, CREATE */
// Search the constructor first, to fail with an error if it's not found before allocating anything else.
@@ -2886,12 +3005,14 @@ Variant CSharpScript::_new(const Variant **p_args, int p_argcount, Variant::Call
}
r_error.error = Variant::CallError::CALL_OK;
- REF ref;
ERR_FAIL_NULL_V(native, Variant());
+ GD_MONO_SCOPE_THREAD_ATTACH;
+
Object *owner = ClassDB::instance(NATIVE_GDMONOCLASS_NAME(native));
+ REF ref;
Reference *r = Object::cast_to<Reference>(owner);
if (r) {
ref = REF(r);
@@ -2929,6 +3050,8 @@ ScriptInstance *CSharpScript::instance_create(Object *p_this) {
}
}
+ GD_MONO_SCOPE_THREAD_ATTACH;
+
Variant::CallError unchecked_error;
return _create_instance(NULL, 0, p_this, Object::cast_to<Reference>(p_this) != NULL, unchecked_error);
}
@@ -2976,6 +3099,8 @@ void CSharpScript::get_script_method_list(List<MethodInfo> *p_list) const {
if (!script_class)
return;
+ GD_MONO_SCOPE_THREAD_ATTACH;
+
// TODO: Filter out things unsuitable for explicit calls, like constructors.
const Vector<GDMonoMethod *> &methods = script_class->get_all_methods();
for (int i = 0; i < methods.size(); ++i) {
@@ -2988,6 +3113,8 @@ bool CSharpScript::has_method(const StringName &p_method) const {
if (!script_class)
return false;
+ GD_MONO_SCOPE_THREAD_ATTACH;
+
return script_class->has_fetched_method_unknown_params(p_method);
}
@@ -2996,6 +3123,8 @@ MethodInfo CSharpScript::get_method_info(const StringName &p_method) const {
if (!script_class)
return MethodInfo();
+ GD_MONO_SCOPE_THREAD_ATTACH;
+
GDMonoClass *top = script_class;
while (top && top != native) {
@@ -3020,6 +3149,8 @@ Error CSharpScript::reload(bool p_keep_state) {
ERR_FAIL_COND_V(!p_keep_state && has_instances, ERR_ALREADY_IN_USE);
+ GD_MONO_SCOPE_THREAD_ATTACH;
+
GDMonoAssembly *project_assembly = GDMono::get_singleton()->get_project_assembly();
if (project_assembly) {
@@ -3247,39 +3378,7 @@ RES ResourceFormatLoaderCSharpScript::load(const String &p_path, const String &p
script->set_path(p_original_path);
-#ifndef TOOLS_ENABLED
-
-#ifdef DEBUG_ENABLED
- // User is responsible for thread attach/detach
- CRASH_COND_MSG(mono_domain_get() == NULL, "Thread is not attached.");
-#endif
-
-#endif
-
-#ifdef TOOLS_ENABLED
- MonoDomain *domain = mono_domain_get();
- if (Engine::get_singleton()->is_editor_hint() && domain == NULL) {
-
- CRASH_COND(Thread::get_caller_id() == Thread::get_main_id());
-
- // Thread is not attached, but we will make an exception in this case
- // because this may be called by one of the editor's worker threads.
- // Attach this thread temporarily to reload the script.
-
- if (domain) {
- MonoThread *mono_thread = mono_thread_attach(domain);
- CRASH_COND(mono_thread == NULL);
- script->reload();
- mono_thread_detach(mono_thread);
- }
-
- } else { // just reload it normally
-#endif
- script->reload();
-
-#ifdef TOOLS_ENABLED
- }
-#endif
+ script->reload();
if (r_error)
*r_error = OK;
diff --git a/modules/mono/csharp_script.h b/modules/mono/csharp_script.h
index 027f429125..30f56e00bd 100644
--- a/modules/mono/csharp_script.h
+++ b/modules/mono/csharp_script.h
@@ -307,6 +307,11 @@ class CSharpLanguage : public ScriptLanguage {
Map<Object *, CSharpScriptBinding> script_bindings;
+#ifdef DEBUG_ENABLED
+ // List of unsafely referenced objects
+ List<ObjectID> unsafely_referenced_objects;
+#endif
+
struct StringNameCache {
StringName _signal_callback;
@@ -458,6 +463,9 @@ public:
Vector<StackInfo> stack_trace_get_info(MonoObject *p_stack_trace);
#endif
+ void post_unsafe_reference(Object *p_obj);
+ void pre_unsafe_unreference(Object *p_obj);
+
CSharpLanguage();
~CSharpLanguage();
};
diff --git a/modules/mono/glue/base_object_glue.cpp b/modules/mono/glue/base_object_glue.cpp
index 04a489f1f9..02246b2f2f 100644
--- a/modules/mono/glue/base_object_glue.cpp
+++ b/modules/mono/glue/base_object_glue.cpp
@@ -108,6 +108,7 @@ void godot_icall_Reference_Disposed(MonoObject *p_obj, Object *p_ptr, MonoBoolea
// Unsafe refcount decrement. The managed instance also counts as a reference.
// See: CSharpLanguage::alloc_instance_binding_data(Object *p_object)
+ CSharpLanguage::get_singleton()->pre_unsafe_unreference(ref);
if (ref->unreference()) {
memdelete(ref);
} else {
diff --git a/modules/mono/icons/icon_c_#.svg b/modules/mono/icons/icon_c_sharp_script.svg
index 69664ca553..69664ca553 100644
--- a/modules/mono/icons/icon_c_#.svg
+++ b/modules/mono/icons/icon_c_sharp_script.svg
diff --git a/modules/mono/mono_gd/gd_mono_assembly.cpp b/modules/mono/mono_gd/gd_mono_assembly.cpp
index 9d7ac5c5ea..6cf5377e2c 100644
--- a/modules/mono/mono_gd/gd_mono_assembly.cpp
+++ b/modules/mono/mono_gd/gd_mono_assembly.cpp
@@ -129,7 +129,7 @@ MonoAssembly *GDMonoAssembly::_search_hook(MonoAssemblyName *aname, void *user_d
(void)user_data; // UNUSED
- String name = mono_assembly_name_get_name(aname);
+ String name = String::utf8(mono_assembly_name_get_name(aname));
bool has_extension = name.ends_with(".dll") || name.ends_with(".exe");
if (no_search)
@@ -176,7 +176,7 @@ MonoAssembly *GDMonoAssembly::_preload_hook(MonoAssemblyName *aname, char **, vo
no_search = true;
in_preload = true;
- String name = mono_assembly_name_get_name(aname);
+ String name = String::utf8(mono_assembly_name_get_name(aname));
bool has_extension = name.ends_with(".dll");
GDMonoAssembly *res = NULL;
@@ -276,7 +276,7 @@ GDMonoAssembly *GDMonoAssembly::_load_assembly_from(const String &p_name, const
}
void GDMonoAssembly::_wrap_mono_assembly(MonoAssembly *assembly) {
- String name = mono_assembly_name_get_name(mono_assembly_get_name(assembly));
+ String name = String::utf8(mono_assembly_name_get_name(mono_assembly_get_name(assembly)));
MonoImage *image = mono_assembly_get_image(assembly);
diff --git a/modules/mono/mono_gd/gd_mono_internals.cpp b/modules/mono/mono_gd/gd_mono_internals.cpp
index 8669182c4e..75aa77c7b0 100644
--- a/modules/mono/mono_gd/gd_mono_internals.cpp
+++ b/modules/mono/mono_gd/gd_mono_internals.cpp
@@ -83,7 +83,9 @@ void tie_managed_to_unmanaged(MonoObject *managed, Object *unmanaged) {
// See: godot_icall_Reference_Dtor(MonoObject *p_obj, Object *p_ptr)
// May not me referenced yet, so we must use init_ref() instead of reference()
- ref->init_ref();
+ if (ref->init_ref()) {
+ CSharpLanguage::get_singleton()->post_unsafe_reference(ref);
+ }
}
// The object was just created, no script instance binding should have been attached
diff --git a/modules/mono/mono_gd/gd_mono_utils.cpp b/modules/mono/mono_gd/gd_mono_utils.cpp
index 3c8aa0c727..4e7f590a69 100644
--- a/modules/mono/mono_gd/gd_mono_utils.cpp
+++ b/modules/mono/mono_gd/gd_mono_utils.cpp
@@ -115,6 +115,7 @@ MonoObject *unmanaged_get_managed(Object *unmanaged) {
// but the managed instance is alive, the refcount will be 1 instead of 0.
// See: godot_icall_Reference_Dtor(MonoObject *p_obj, Object *p_ptr)
ref->reference();
+ CSharpLanguage::get_singleton()->post_unsafe_reference(ref);
}
return mono_object;
@@ -124,10 +125,12 @@ void set_main_thread(MonoThread *p_thread) {
mono_thread_set_main(p_thread);
}
-void attach_current_thread() {
- ERR_FAIL_COND(!GDMono::get_singleton()->is_runtime_initialized());
- MonoThread *mono_thread = mono_thread_attach(mono_get_root_domain());
- ERR_FAIL_NULL(mono_thread);
+MonoThread *attach_current_thread() {
+ ERR_FAIL_COND_V(!GDMono::get_singleton()->is_runtime_initialized(), NULL);
+ MonoDomain *scripts_domain = GDMono::get_singleton()->get_scripts_domain();
+ MonoThread *mono_thread = mono_thread_attach(scripts_domain ? scripts_domain : mono_get_root_domain());
+ ERR_FAIL_NULL_V(mono_thread, NULL);
+ return mono_thread;
}
void detach_current_thread() {
@@ -137,10 +140,20 @@ void detach_current_thread() {
mono_thread_detach(mono_thread);
}
+void detach_current_thread(MonoThread *p_mono_thread) {
+ ERR_FAIL_COND(!GDMono::get_singleton()->is_runtime_initialized());
+ ERR_FAIL_NULL(p_mono_thread);
+ mono_thread_detach(p_mono_thread);
+}
+
MonoThread *get_current_thread() {
return mono_thread_current();
}
+bool is_thread_attached() {
+ return mono_domain_get() != NULL;
+}
+
void runtime_object_init(MonoObject *p_this_obj, GDMonoClass *p_class, MonoException **r_exc) {
GDMonoMethod *ctor = p_class->get_method(".ctor", 0);
ERR_FAIL_NULL(ctor);
@@ -616,4 +629,19 @@ GDMonoClass *make_generic_dictionary_type(MonoReflectionType *p_key_reftype, Mon
} // namespace Marshal
+ScopeThreadAttach::ScopeThreadAttach() :
+ mono_thread(NULL) {
+ if (likely(GDMono::get_singleton()->is_runtime_initialized()) && unlikely(!mono_domain_get())) {
+ mono_thread = GDMonoUtils::attach_current_thread();
+ }
+}
+
+ScopeThreadAttach::~ScopeThreadAttach() {
+ if (unlikely(mono_thread)) {
+ GDMonoUtils::detach_current_thread(mono_thread);
+ }
+}
+
+// namespace Marshal
+
} // namespace GDMonoUtils
diff --git a/modules/mono/mono_gd/gd_mono_utils.h b/modules/mono/mono_gd/gd_mono_utils.h
index d9eb912cd7..db9f99bfdc 100644
--- a/modules/mono/mono_gd/gd_mono_utils.h
+++ b/modules/mono/mono_gd/gd_mono_utils.h
@@ -83,9 +83,11 @@ _FORCE_INLINE_ void hash_combine(uint32_t &p_hash, const uint32_t &p_with_hash)
MonoObject *unmanaged_get_managed(Object *unmanaged);
void set_main_thread(MonoThread *p_thread);
-void attach_current_thread();
+MonoThread *attach_current_thread();
void detach_current_thread();
+void detach_current_thread(MonoThread *p_mono_thread);
MonoThread *get_current_thread();
+bool is_thread_attached();
_FORCE_INLINE_ bool is_main_thread() {
return mono_domain_get() != NULL && mono_thread_get_main() == mono_thread_current();
@@ -142,6 +144,14 @@ uint64_t unbox_enum_value(MonoObject *p_boxed, MonoType *p_enum_basetype, bool &
void dispose(MonoObject *p_mono_object, MonoException **r_exc);
+struct ScopeThreadAttach {
+ ScopeThreadAttach();
+ ~ScopeThreadAttach();
+
+private:
+ MonoThread *mono_thread;
+};
+
} // namespace GDMonoUtils
#define NATIVE_GDMONOCLASS_NAME(m_class) (GDMonoMarshal::mono_string_to_godot((MonoString *)m_class->get_field(BINDINGS_NATIVE_NAME_FIELD)->get_value(NULL)))
@@ -153,4 +163,15 @@ void dispose(MonoObject *p_mono_object, MonoException **r_exc);
#define GD_MONO_END_RUNTIME_INVOKE \
_runtime_invoke_count_ref -= 1;
+#define GD_MONO_SCOPE_THREAD_ATTACH \
+ GDMonoUtils::ScopeThreadAttach __gdmono__scope__thread__attach__; \
+ (void)__gdmono__scope__thread__attach__;
+
+#ifdef DEBUG_ENABLED
+#define GD_MONO_ASSERT_THREAD_ATTACHED \
+ { CRASH_COND(!GDMonoUtils::is_thread_attached()); }
+#else
+#define GD_MONO_ASSERT_THREAD_ATTACHED
+#endif
+
#endif // GD_MONOUTILS_H
diff --git a/modules/opensimplex/noise_texture.cpp b/modules/opensimplex/noise_texture.cpp
index e0cdfb33b4..aa1c822813 100644
--- a/modules/opensimplex/noise_texture.cpp
+++ b/modules/opensimplex/noise_texture.cpp
@@ -53,6 +53,10 @@ NoiseTexture::NoiseTexture() {
NoiseTexture::~NoiseTexture() {
VS::get_singleton()->free(texture);
+ if (noise_thread) {
+ Thread::wait_to_finish(noise_thread);
+ memdelete(noise_thread);
+ }
}
void NoiseTexture::_bind_methods() {
@@ -73,6 +77,7 @@ void NoiseTexture::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_bump_strength"), &NoiseTexture::get_bump_strength);
ClassDB::bind_method(D_METHOD("_update_texture"), &NoiseTexture::_update_texture);
+ ClassDB::bind_method(D_METHOD("_queue_update"), &NoiseTexture::_queue_update);
ClassDB::bind_method(D_METHOD("_generate_texture"), &NoiseTexture::_generate_texture);
ClassDB::bind_method(D_METHOD("_thread_done", "image"), &NoiseTexture::_thread_done);
@@ -130,8 +135,6 @@ void NoiseTexture::_queue_update() {
Ref<Image> NoiseTexture::_generate_texture() {
- update_queued = false;
-
if (noise.is_null()) return Ref<Image>();
Ref<Image> image;
@@ -171,17 +174,18 @@ void NoiseTexture::_update_texture() {
Ref<Image> image = _generate_texture();
_set_texture_data(image);
}
+ update_queued = false;
}
void NoiseTexture::set_noise(Ref<OpenSimplexNoise> p_noise) {
if (p_noise == noise)
return;
if (noise.is_valid()) {
- noise->disconnect(CoreStringNames::get_singleton()->changed, this, "_update_texture");
+ noise->disconnect(CoreStringNames::get_singleton()->changed, this, "_queue_update");
}
noise = p_noise;
if (noise.is_valid()) {
- noise->connect(CoreStringNames::get_singleton()->changed, this, "_update_texture");
+ noise->connect(CoreStringNames::get_singleton()->changed, this, "_queue_update");
}
_queue_update();
}
diff --git a/modules/squish/image_compress_squish.cpp b/modules/squish/image_compress_squish.cpp
index ef4ea93e57..58b8115dfc 100644
--- a/modules/squish/image_compress_squish.cpp
+++ b/modules/squish/image_compress_squish.cpp
@@ -73,7 +73,6 @@ void image_decompress_squish(Image *p_image) {
p_image->create(p_image->get_width(), p_image->get_height(), p_image->has_mipmaps(), target_format, data);
}
-#ifdef TOOLS_ENABLED
void image_compress_squish(Image *p_image, float p_lossy_quality, Image::CompressSource p_source) {
if (p_image->get_format() >= Image::FORMAT_DXT1)
@@ -203,4 +202,3 @@ void image_compress_squish(Image *p_image, float p_lossy_quality, Image::Compres
p_image->create(p_image->get_width(), p_image->get_height(), p_image->has_mipmaps(), target_format, data);
}
}
-#endif
diff --git a/modules/squish/image_compress_squish.h b/modules/squish/image_compress_squish.h
index 2666815e47..b5a209ceb9 100644
--- a/modules/squish/image_compress_squish.h
+++ b/modules/squish/image_compress_squish.h
@@ -33,9 +33,7 @@
#include "core/image.h"
-#ifdef TOOLS_ENABLED
void image_compress_squish(Image *p_image, float p_lossy_quality, Image::CompressSource p_source);
-#endif
void image_decompress_squish(Image *p_image);
#endif // IMAGE_COMPRESS_SQUISH_H
diff --git a/modules/squish/register_types.cpp b/modules/squish/register_types.cpp
index 1cd551defb..2a0cf82b56 100644
--- a/modules/squish/register_types.cpp
+++ b/modules/squish/register_types.cpp
@@ -33,9 +33,7 @@
void register_squish_types() {
-#ifdef TOOLS_ENABLED
Image::set_compress_bc_func(image_compress_squish);
-#endif
Image::_image_decompress_bc = image_decompress_squish;
}
diff --git a/modules/stb_vorbis/doc_classes/AudioStreamOGGVorbis.xml b/modules/stb_vorbis/doc_classes/AudioStreamOGGVorbis.xml
index 9403199398..102a9b4236 100644
--- a/modules/stb_vorbis/doc_classes/AudioStreamOGGVorbis.xml
+++ b/modules/stb_vorbis/doc_classes/AudioStreamOGGVorbis.xml
@@ -15,8 +15,10 @@
Contains the audio data in bytes.
</member>
<member name="loop" type="bool" setter="set_loop" getter="has_loop" default="false">
+ If [code]true[/code], the stream will automatically loop when it reaches the end.
</member>
<member name="loop_offset" type="float" setter="set_loop_offset" getter="get_loop_offset" default="0.0">
+ Time in seconds at which the stream starts after being looped.
</member>
</members>
<constants>
diff --git a/modules/visual_script/visual_script_editor.cpp b/modules/visual_script/visual_script_editor.cpp
index 4bfd4f48ce..ec20698ae8 100644
--- a/modules/visual_script/visual_script_editor.cpp
+++ b/modules/visual_script/visual_script_editor.cpp
@@ -575,7 +575,7 @@ void VisualScriptEditor::_update_graph(int p_only_id) {
Button *btn = memnew(Button);
btn->set_text(TTR("Add Input Port"));
hbnc->add_child(btn);
- btn->connect("pressed", this, "_add_input_port", varray(E->get()));
+ btn->connect("pressed", this, "_add_input_port", varray(E->get()), CONNECT_DEFERRED);
}
if (nd_list->is_output_port_editable()) {
if (nd_list->is_input_port_editable())
@@ -584,7 +584,7 @@ void VisualScriptEditor::_update_graph(int p_only_id) {
Button *btn = memnew(Button);
btn->set_text(TTR("Add Output Port"));
hbnc->add_child(btn);
- btn->connect("pressed", this, "_add_output_port", varray(E->get()));
+ btn->connect("pressed", this, "_add_output_port", varray(E->get()), CONNECT_DEFERRED);
}
gnode->add_child(hbnc);
} else if (Object::cast_to<VisualScriptExpression>(node.ptr())) {
diff --git a/modules/websocket/doc_classes/WebSocketClient.xml b/modules/websocket/doc_classes/WebSocketClient.xml
index 705e3485f5..52a98d8c32 100644
--- a/modules/websocket/doc_classes/WebSocketClient.xml
+++ b/modules/websocket/doc_classes/WebSocketClient.xml
@@ -27,7 +27,8 @@
Connects to the given URL requesting one of the given [code]protocols[/code] as sub-protocol. If the list empty (default), no sub-protocol will be requested.
If [code]true[/code] is passed as [code]gd_mp_api[/code], the client will behave like a network peer for the [MultiplayerAPI], connections to non-Godot servers will not work, and [signal data_received] will not be emitted.
If [code]false[/code] is passed instead (default), you must call [PacketPeer] functions ([code]put_packet[/code], [code]get_packet[/code], etc.) on the [WebSocketPeer] returned via [code]get_peer(1)[/code] and not on this object directly (e.g. [code]get_peer(1).put_packet(data)[/code]).
- You can optionally pass a list of [code]custom_headers[/code] to be added to the handshake HTTP request (not supported in HTML5 platform).
+ You can optionally pass a list of [code]custom_headers[/code] to be added to the handshake HTTP request.
+ [b]Note:[/b] Specifying [code]custom_headers[/code] is not supported in HTML5 exports due to browsers restrictions.
</description>
</method>
<method name="disconnect_from_host">
@@ -59,6 +60,7 @@
<members>
<member name="trusted_ssl_certificate" type="X509Certificate" setter="set_trusted_ssl_certificate" getter="get_trusted_ssl_certificate">
If specified, this [X509Certificate] will be the only one accepted when connecting to an SSL host. Any other certificate provided by the server will be regarded as invalid.
+ [b]Note:[/b] Specifying a custom [code]trusted_ssl_certificate[/code] is not supported in HTML5 exports due to browsers restrictions.
</member>
<member name="verify_ssl" type="bool" setter="set_verify_ssl_enabled" getter="is_verify_ssl_enabled">
If [code]true[/code], SSL certificate verification is enabled.
diff --git a/modules/websocket/doc_classes/WebSocketServer.xml b/modules/websocket/doc_classes/WebSocketServer.xml
index 86f2dae64f..2074a10fa9 100644
--- a/modules/websocket/doc_classes/WebSocketServer.xml
+++ b/modules/websocket/doc_classes/WebSocketServer.xml
@@ -6,7 +6,7 @@
<description>
This class implements a WebSocket server that can also support the high-level multiplayer API.
After starting the server ([method listen]), you will need to [method NetworkedMultiplayerPeer.poll] it at regular intervals (e.g. inside [method Node._process]). When clients connect, disconnect, or send data, you will receive the appropriate signal.
- [b]Note:[/b] This class will not work in HTML5 exports due to browser restrictions.
+ [b]Note:[/b] Not available in HTML5 exports.
</description>
<tutorials>
</tutorials>
@@ -83,6 +83,9 @@
</method>
</methods>
<members>
+ <member name="bind_ip" type="String" setter="set_bind_ip" getter="get_bind_ip" default="&quot;*&quot;">
+ When not set to [code]*[/code] will restrict incoming connections to the specified IP address. Setting [code]bind_ip[/code] to [code]127.0.0.1[/code] will cause the server to listen only to the local host.
+ </member>
<member name="ca_chain" type="X509Certificate" setter="set_ca_chain" getter="get_ca_chain">
When using SSL (see [member private_key] and [member ssl_certificate]), you can set this to a valid [X509Certificate] to be provided as additional CA chain information during the SSL handshake.
</member>
diff --git a/modules/websocket/websocket_server.cpp b/modules/websocket/websocket_server.cpp
index ded1850846..76e88d72b9 100644
--- a/modules/websocket/websocket_server.cpp
+++ b/modules/websocket/websocket_server.cpp
@@ -34,6 +34,7 @@ GDCINULL(WebSocketServer);
WebSocketServer::WebSocketServer() {
_peer_id = 1;
+ bind_ip = IP_Address("*");
}
WebSocketServer::~WebSocketServer() {
@@ -49,6 +50,10 @@ void WebSocketServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_peer_port", "id"), &WebSocketServer::get_peer_port);
ClassDB::bind_method(D_METHOD("disconnect_peer", "id", "code", "reason"), &WebSocketServer::disconnect_peer, DEFVAL(1000), DEFVAL(""));
+ ClassDB::bind_method(D_METHOD("get_bind_ip"), &WebSocketServer::get_bind_ip);
+ ClassDB::bind_method(D_METHOD("set_bind_ip"), &WebSocketServer::set_bind_ip);
+ ADD_PROPERTY(PropertyInfo(Variant::STRING, "bind_ip"), "set_bind_ip", "get_bind_ip");
+
ClassDB::bind_method(D_METHOD("get_private_key"), &WebSocketServer::get_private_key);
ClassDB::bind_method(D_METHOD("set_private_key"), &WebSocketServer::set_private_key);
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "private_key", PROPERTY_HINT_RESOURCE_TYPE, "CryptoKey", 0), "set_private_key", "get_private_key");
@@ -67,6 +72,16 @@ void WebSocketServer::_bind_methods() {
ADD_SIGNAL(MethodInfo("data_received", PropertyInfo(Variant::INT, "id")));
}
+IP_Address WebSocketServer::get_bind_ip() const {
+ return bind_ip;
+}
+
+void WebSocketServer::set_bind_ip(const IP_Address &p_bind_ip) {
+ ERR_FAIL_COND(is_listening());
+ ERR_FAIL_COND(!p_bind_ip.is_valid() && !p_bind_ip.is_wildcard());
+ bind_ip = p_bind_ip;
+}
+
Ref<CryptoKey> WebSocketServer::get_private_key() const {
return private_key;
}
diff --git a/modules/websocket/websocket_server.h b/modules/websocket/websocket_server.h
index bfdac11489..3ce4dbe711 100644
--- a/modules/websocket/websocket_server.h
+++ b/modules/websocket/websocket_server.h
@@ -41,6 +41,8 @@ class WebSocketServer : public WebSocketMultiplayerPeer {
GDCLASS(WebSocketServer, WebSocketMultiplayerPeer);
GDCICLASS(WebSocketServer);
+ IP_Address bind_ip;
+
protected:
static void _bind_methods();
@@ -67,6 +69,9 @@ public:
void _on_disconnect(int32_t p_peer_id, bool p_was_clean);
void _on_close_request(int32_t p_peer_id, int p_code, String p_reason);
+ IP_Address get_bind_ip() const;
+ void set_bind_ip(const IP_Address &p_bind_ip);
+
Ref<CryptoKey> get_private_key() const;
void set_private_key(Ref<CryptoKey> p_key);
diff --git a/modules/websocket/wsl_server.cpp b/modules/websocket/wsl_server.cpp
index c98c62cce9..c3dd79a89c 100644
--- a/modules/websocket/wsl_server.cpp
+++ b/modules/websocket/wsl_server.cpp
@@ -165,7 +165,7 @@ Error WSLServer::listen(int p_port, const Vector<String> p_protocols, bool gd_mp
for (int i = 0; i < p_protocols.size(); i++) {
pw[i] = p_protocols[i].strip_edges();
}
- _server->listen(p_port);
+ _server->listen(p_port, bind_ip);
return OK;
}
diff --git a/platform/android/dir_access_jandroid.cpp b/platform/android/dir_access_jandroid.cpp
index 69178317f7..f52b511522 100644
--- a/platform/android/dir_access_jandroid.cpp
+++ b/platform/android/dir_access_jandroid.cpp
@@ -110,7 +110,6 @@ String DirAccessJAndroid::get_drive(int p_drive) {
Error DirAccessJAndroid::change_dir(String p_dir) {
JNIEnv *env = ThreadAndroid::get_env();
- p_dir = p_dir.simplify_path();
if (p_dir == "" || p_dir == "." || (p_dir == ".." && current_dir == ""))
return OK;
diff --git a/platform/android/export/export.cpp b/platform/android/export/export.cpp
index 9167a291f8..eb461860ed 100644
--- a/platform/android/export/export.cpp
+++ b/platform/android/export/export.cpp
@@ -30,6 +30,7 @@
#include "export.h"
+#include "core/io/image_loader.h"
#include "core/io/marshalls.h"
#include "core/io/zip_io.h"
#include "core/os/dir_access.h"
@@ -37,6 +38,7 @@
#include "core/os/os.h"
#include "core/project_settings.h"
#include "core/version.h"
+#include "drivers/png/png_driver_common.h"
#include "editor/editor_export.h"
#include "editor/editor_log.h"
#include "editor/editor_node.h"
@@ -196,16 +198,40 @@ static const char *android_perms[] = {
};
struct LauncherIcon {
- const char *option_id;
const char *export_path;
+ int dimensions;
};
-static const LauncherIcon launcher_icons[] = {
- { "launcher_icons/xxxhdpi_192x192", "res/drawable-xxxhdpi-v4/icon.png" },
- { "launcher_icons/xxhdpi_144x144", "res/drawable-xxhdpi-v4/icon.png" },
- { "launcher_icons/xhdpi_96x96", "res/drawable-xhdpi-v4/icon.png" },
- { "launcher_icons/hdpi_72x72", "res/drawable-hdpi-v4/icon.png" },
- { "launcher_icons/mdpi_48x48", "res/drawable-mdpi-v4/icon.png" }
+static const int icon_densities_count = 6;
+static const char *launcher_icon_option = "launcher_icon/xxxhdpi_192x192";
+static const char *launcher_adaptive_icon_foreground_option = "launcher_adaptive_icon_foreground/xxxhdpi_432x432";
+static const char *launcher_adaptive_icon_background_option = "launcher_adaptive_icon_background/xxxhdpi_432x432";
+
+static const LauncherIcon launcher_icons[icon_densities_count] = {
+ { "res/mipmap-xxxhdpi-v4/icon.png", 192 },
+ { "res/mipmap-xxhdpi-v4/icon.png", 144 },
+ { "res/mipmap-xhdpi-v4/icon.png", 96 },
+ { "res/mipmap-hdpi-v4/icon.png", 72 },
+ { "res/mipmap-mdpi-v4/icon.png", 48 },
+ { "res/mipmap/icon.png", 192 }
+};
+
+static const LauncherIcon launcher_adaptive_icon_foregrounds[icon_densities_count] = {
+ { "res/mipmap-xxxhdpi-v4/icon_foreground.png", 432 },
+ { "res/mipmap-xxhdpi-v4/icon_foreground.png", 324 },
+ { "res/mipmap-xhdpi-v4/icon_foreground.png", 216 },
+ { "res/mipmap-hdpi-v4/icon_foreground.png", 162 },
+ { "res/mipmap-mdpi-v4/icon_foreground.png", 108 },
+ { "res/mipmap/icon_foreground.png", 432 }
+};
+
+static const LauncherIcon launcher_adaptive_icon_backgrounds[icon_densities_count] = {
+ { "res/mipmap-xxxhdpi-v4/icon_background.png", 432 },
+ { "res/mipmap-xxhdpi-v4/icon_background.png", 324 },
+ { "res/mipmap-xhdpi-v4/icon_background.png", 216 },
+ { "res/mipmap-hdpi-v4/icon_background.png", 162 },
+ { "res/mipmap-mdpi-v4/icon_background.png", 108 },
+ { "res/mipmap/icon_background.png", 432 }
};
class EditorExportPlatformAndroid : public EditorExportPlatform {
@@ -680,7 +706,7 @@ class EditorExportPlatformAndroid : public EditorExportPlatform {
bool screen_support_large = p_preset->get("screen/support_large");
bool screen_support_xlarge = p_preset->get("screen/support_xlarge");
- int xr_mode_index = p_preset->get("graphics/xr_mode");
+ int xr_mode_index = p_preset->get("xr_features/xr_mode");
Vector<String> perms;
@@ -859,135 +885,174 @@ class EditorExportPlatformAndroid : public EditorExportPlatform {
uint32_t name = decode_uint32(&p_manifest[iofs + 12]);
String tname = string_table[name];
- int dof_index = p_preset->get("graphics/degrees_of_freedom"); // 0: none, 1: 3dof and 6dof, 2: 6dof
+ if (tname == "uses-feature") {
+ Vector<String> feature_names;
+ Vector<bool> feature_required_list;
+ Vector<int> feature_versions;
+
+ if (xr_mode_index == 1 /* XRMode.OVR */) {
+ // Check for degrees of freedom
+ int dof_index = p_preset->get("xr_features/degrees_of_freedom"); // 0: none, 1: 3dof and 6dof, 2: 6dof
+
+ if (dof_index > 0) {
+ feature_names.push_back("android.hardware.vr.headtracking");
+ feature_required_list.push_back(dof_index == 2);
+ feature_versions.push_back(1);
+ }
+
+ // Check for hand tracking
+ int hand_tracking_index = p_preset->get("xr_features/hand_tracking"); // 0: none, 1: optional, 2: required
+ if (hand_tracking_index > 0) {
+ feature_names.push_back("oculus.software.handtracking");
+ feature_required_list.push_back(hand_tracking_index == 2);
+ feature_versions.push_back(-1); // no version attribute should be added.
- if (tname == "uses-feature" && dof_index > 0) {
- if (xr_mode_index == 0) {
- WARN_PRINT("VR DOF feature setting is only valid for oculus HMDs with an XR mode set to VR");
+ if (perms.find("oculus.permission.handtracking") == -1) {
+ perms.push_back("oculus.permission.handtracking");
+ }
+ }
}
- ofs += 24; // skip over end tag
- // save manifest ending so we can restore it
- Vector<uint8_t> manifest_end;
- uint32_t manifest_cur_size = p_manifest.size();
+ if (feature_names.size() > 0) {
+ ofs += 24; // skip over end tag
- manifest_end.resize(p_manifest.size() - ofs);
- memcpy(manifest_end.ptrw(), &p_manifest[ofs], manifest_end.size());
+ // save manifest ending so we can restore it
+ Vector<uint8_t> manifest_end;
+ uint32_t manifest_cur_size = p_manifest.size();
- int32_t attr_name_string = string_table.find("name");
- ERR_FAIL_COND_MSG(attr_name_string == -1, "Template does not have 'name' attribute.");
+ manifest_end.resize(p_manifest.size() - ofs);
+ memcpy(manifest_end.ptrw(), &p_manifest[ofs], manifest_end.size());
- int32_t ns_android_string = string_table.find("http://schemas.android.com/apk/res/android");
- if (ns_android_string == -1) {
- string_table.push_back("http://schemas.android.com/apk/res/android");
- ns_android_string = string_table.size() - 1;
- }
+ int32_t attr_name_string = string_table.find("name");
+ ERR_FAIL_COND_MSG(attr_name_string == -1, "Template does not have 'name' attribute.");
- int32_t attr_uses_permission_string = string_table.find("uses-feature");
- if (attr_uses_permission_string == -1) {
- string_table.push_back("uses-feature");
- attr_uses_permission_string = string_table.size() - 1;
- }
+ int32_t ns_android_string = string_table.find("http://schemas.android.com/apk/res/android");
+ if (ns_android_string == -1) {
+ string_table.push_back("http://schemas.android.com/apk/res/android");
+ ns_android_string = string_table.size() - 1;
+ }
- int32_t attr_required_string = string_table.find("required");
- if (attr_required_string == -1) {
- string_table.push_back("required");
- attr_required_string = string_table.size() - 1;
- }
+ int32_t attr_uses_feature_string = string_table.find("uses-feature");
+ if (attr_uses_feature_string == -1) {
+ string_table.push_back("uses-feature");
+ attr_uses_feature_string = string_table.size() - 1;
+ }
- int32_t attr_version_string = string_table.find("version");
- if (attr_version_string == -1) {
- string_table.push_back("version");
- attr_version_string = string_table.size() - 1;
- }
+ int32_t attr_required_string = string_table.find("required");
+ if (attr_required_string == -1) {
+ string_table.push_back("required");
+ attr_required_string = string_table.size() - 1;
+ }
- String required_value_string;
- if (dof_index == 1) {
- required_value_string = "false";
- } else if (dof_index == 2) {
- required_value_string = "true";
- } else {
- ERR_FAIL_MSG("Unknown DoF index: " + itos(dof_index) + ".");
- }
- int32_t required_value = string_table.find(required_value_string);
- if (required_value == -1) {
- string_table.push_back(required_value_string);
- required_value = string_table.size() - 1;
- }
+ for (int i = 0; i < feature_names.size(); i++) {
+ String feature_name = feature_names[i];
+ bool feature_required = feature_required_list[i];
+ int feature_version = feature_versions[i];
+ bool has_version_attribute = feature_version != -1;
- int32_t version_value = string_table.find("1");
- if (version_value == -1) {
- string_table.push_back("1");
- version_value = string_table.size() - 1;
- }
+ print_line("Adding feature " + feature_name);
- int32_t feature_string = string_table.find("android.hardware.vr.headtracking");
- if (feature_string == -1) {
- string_table.push_back("android.hardware.vr.headtracking");
- feature_string = string_table.size() - 1;
- }
+ int32_t feature_string = string_table.find(feature_name);
+ if (feature_string == -1) {
+ string_table.push_back(feature_name);
+ feature_string = string_table.size() - 1;
+ }
- {
- manifest_cur_size += 96 + 20; // node and three attrs + end node
- p_manifest.resize(manifest_cur_size);
+ String required_value_string = feature_required ? "true" : "false";
+ int32_t required_value = string_table.find(required_value_string);
+ if (required_value == -1) {
+ string_table.push_back(required_value_string);
+ required_value = string_table.size() - 1;
+ }
- // start tag
- encode_uint16(0x102, &p_manifest.write[ofs]); // type
- encode_uint16(16, &p_manifest.write[ofs + 2]); // headersize
- encode_uint32(96, &p_manifest.write[ofs + 4]); // size
- encode_uint32(0, &p_manifest.write[ofs + 8]); // lineno
- encode_uint32(-1, &p_manifest.write[ofs + 12]); // comment
- encode_uint32(-1, &p_manifest.write[ofs + 16]); // ns
- encode_uint32(attr_uses_permission_string, &p_manifest.write[ofs + 20]); // name
- encode_uint16(20, &p_manifest.write[ofs + 24]); // attr_start
- encode_uint16(20, &p_manifest.write[ofs + 26]); // attr_size
- encode_uint16(3, &p_manifest.write[ofs + 28]); // num_attrs
- encode_uint16(0, &p_manifest.write[ofs + 30]); // id_index
- encode_uint16(0, &p_manifest.write[ofs + 32]); // class_index
- encode_uint16(0, &p_manifest.write[ofs + 34]); // style_index
+ int32_t attr_version_string = -1;
+ int32_t version_value = -1;
+ int tag_size;
+ int attr_count;
+ if (has_version_attribute) {
+ attr_version_string = string_table.find("version");
+ if (attr_version_string == -1) {
+ string_table.push_back("version");
+ attr_version_string = string_table.size() - 1;
+ }
- // android:name attribute
- encode_uint32(ns_android_string, &p_manifest.write[ofs + 36]); // ns
- encode_uint32(attr_name_string, &p_manifest.write[ofs + 40]); // 'name'
- encode_uint32(feature_string, &p_manifest.write[ofs + 44]); // raw_value
- encode_uint16(8, &p_manifest.write[ofs + 48]); // typedvalue_size
- p_manifest.write[ofs + 50] = 0; // typedvalue_always0
- p_manifest.write[ofs + 51] = 0x03; // typedvalue_type (string)
- encode_uint32(feature_string, &p_manifest.write[ofs + 52]); // typedvalue reference
-
- // android:required attribute
- encode_uint32(ns_android_string, &p_manifest.write[ofs + 56]); // ns
- encode_uint32(attr_required_string, &p_manifest.write[ofs + 60]); // 'name'
- encode_uint32(required_value, &p_manifest.write[ofs + 64]); // raw_value
- encode_uint16(8, &p_manifest.write[ofs + 68]); // typedvalue_size
- p_manifest.write[ofs + 70] = 0; // typedvalue_always0
- p_manifest.write[ofs + 71] = 0x03; // typedvalue_type (string)
- encode_uint32(required_value, &p_manifest.write[ofs + 72]); // typedvalue reference
-
- // android:version attribute
- encode_uint32(ns_android_string, &p_manifest.write[ofs + 76]); // ns
- encode_uint32(attr_version_string, &p_manifest.write[ofs + 80]); // 'name'
- encode_uint32(version_value, &p_manifest.write[ofs + 84]); // raw_value
- encode_uint16(8, &p_manifest.write[ofs + 88]); // typedvalue_size
- p_manifest.write[ofs + 90] = 0; // typedvalue_always0
- p_manifest.write[ofs + 91] = 0x03; // typedvalue_type (string)
- encode_uint32(version_value, &p_manifest.write[ofs + 92]); // typedvalue reference
-
- ofs += 96;
+ version_value = string_table.find(itos(feature_version));
+ if (version_value == -1) {
+ string_table.push_back(itos(feature_version));
+ version_value = string_table.size() - 1;
+ }
- // end tag
- encode_uint16(0x103, &p_manifest.write[ofs]); // type
- encode_uint16(16, &p_manifest.write[ofs + 2]); // headersize
- encode_uint32(24, &p_manifest.write[ofs + 4]); // size
- encode_uint32(0, &p_manifest.write[ofs + 8]); // lineno
- encode_uint32(-1, &p_manifest.write[ofs + 12]); // comment
- encode_uint32(-1, &p_manifest.write[ofs + 16]); // ns
- encode_uint32(attr_uses_permission_string, &p_manifest.write[ofs + 20]); // name
+ tag_size = 96; // node and three attrs + end node
+ attr_count = 3;
+ } else {
+ tag_size = 76; // node and two attrs + end node
+ attr_count = 2;
+ }
+ manifest_cur_size += tag_size + 24;
+ p_manifest.resize(manifest_cur_size);
+
+ // start tag
+ encode_uint16(0x102, &p_manifest.write[ofs]); // type
+ encode_uint16(16, &p_manifest.write[ofs + 2]); // headersize
+ encode_uint32(tag_size, &p_manifest.write[ofs + 4]); // size
+ encode_uint32(0, &p_manifest.write[ofs + 8]); // lineno
+ encode_uint32(-1, &p_manifest.write[ofs + 12]); // comment
+ encode_uint32(-1, &p_manifest.write[ofs + 16]); // ns
+ encode_uint32(attr_uses_feature_string, &p_manifest.write[ofs + 20]); // name
+ encode_uint16(20, &p_manifest.write[ofs + 24]); // attr_start
+ encode_uint16(20, &p_manifest.write[ofs + 26]); // attr_size
+ encode_uint16(attr_count, &p_manifest.write[ofs + 28]); // num_attrs
+ encode_uint16(0, &p_manifest.write[ofs + 30]); // id_index
+ encode_uint16(0, &p_manifest.write[ofs + 32]); // class_index
+ encode_uint16(0, &p_manifest.write[ofs + 34]); // style_index
+
+ // android:name attribute
+ encode_uint32(ns_android_string, &p_manifest.write[ofs + 36]); // ns
+ encode_uint32(attr_name_string, &p_manifest.write[ofs + 40]); // 'name'
+ encode_uint32(feature_string, &p_manifest.write[ofs + 44]); // raw_value
+ encode_uint16(8, &p_manifest.write[ofs + 48]); // typedvalue_size
+ p_manifest.write[ofs + 50] = 0; // typedvalue_always0
+ p_manifest.write[ofs + 51] = 0x03; // typedvalue_type (string)
+ encode_uint32(feature_string, &p_manifest.write[ofs + 52]); // typedvalue reference
+
+ // android:required attribute
+ encode_uint32(ns_android_string, &p_manifest.write[ofs + 56]); // ns
+ encode_uint32(attr_required_string, &p_manifest.write[ofs + 60]); // 'name'
+ encode_uint32(required_value, &p_manifest.write[ofs + 64]); // raw_value
+ encode_uint16(8, &p_manifest.write[ofs + 68]); // typedvalue_size
+ p_manifest.write[ofs + 70] = 0; // typedvalue_always0
+ p_manifest.write[ofs + 71] = 0x03; // typedvalue_type (string)
+ encode_uint32(required_value, &p_manifest.write[ofs + 72]); // typedvalue reference
+
+ ofs += 76;
+
+ if (has_version_attribute) {
+ // android:version attribute
+ encode_uint32(ns_android_string, &p_manifest.write[ofs]); // ns
+ encode_uint32(attr_version_string, &p_manifest.write[ofs + 4]); // 'name'
+ encode_uint32(version_value, &p_manifest.write[ofs + 8]); // raw_value
+ encode_uint16(8, &p_manifest.write[ofs + 12]); // typedvalue_size
+ p_manifest.write[ofs + 14] = 0; // typedvalue_always0
+ p_manifest.write[ofs + 15] = 0x03; // typedvalue_type (string)
+ encode_uint32(version_value, &p_manifest.write[ofs + 16]); // typedvalue reference
+
+ ofs += 20;
+ }
- ofs += 24;
+ // end tag
+ encode_uint16(0x103, &p_manifest.write[ofs]); // type
+ encode_uint16(16, &p_manifest.write[ofs + 2]); // headersize
+ encode_uint32(24, &p_manifest.write[ofs + 4]); // size
+ encode_uint32(0, &p_manifest.write[ofs + 8]); // lineno
+ encode_uint32(-1, &p_manifest.write[ofs + 12]); // comment
+ encode_uint32(-1, &p_manifest.write[ofs + 16]); // ns
+ encode_uint32(attr_uses_feature_string, &p_manifest.write[ofs + 20]); // name
+
+ ofs += 24;
+ }
+ memcpy(&p_manifest.write[ofs], manifest_end.ptr(), manifest_end.size());
+ ofs -= 24; // go back over back end
}
- memcpy(&p_manifest.write[ofs], manifest_end.ptr(), manifest_end.size());
- ofs -= 24; // go back over back end
}
if (tname == "manifest") {
@@ -1259,6 +1324,27 @@ class EditorExportPlatformAndroid : public EditorExportPlatform {
//printf("end\n");
}
+ void _process_launcher_icons(const String &p_processing_file_name, const Ref<Image> &p_source_image, const LauncherIcon p_icon, Vector<uint8_t> &p_data) {
+ if (p_processing_file_name == p_icon.export_path) {
+ Ref<Image> working_image = p_source_image;
+
+ if (p_source_image->get_width() != p_icon.dimensions || p_source_image->get_height() != p_icon.dimensions) {
+ working_image = p_source_image->duplicate();
+ working_image->resize(p_icon.dimensions, p_icon.dimensions, Image::Interpolation::INTERPOLATE_LANCZOS);
+ }
+
+ PoolVector<uint8_t> png_buffer;
+ Error err = PNGDriverCommon::image_to_png(working_image, png_buffer);
+ if (err == OK) {
+ p_data.resize(png_buffer.size());
+ memcpy(p_data.ptrw(), png_buffer.read().ptr(), p_data.size());
+ } else {
+ String err_str = String("Failed to convert resized icon (") + p_processing_file_name + ") to png.";
+ WARN_PRINT(err_str.utf8().get_data());
+ }
+ }
+ }
+
static Vector<String> get_enabled_abis(const Ref<EditorExportPreset> &p_preset) {
Vector<String> abis = get_abis();
Vector<String> enabled_abis;
@@ -1295,13 +1381,14 @@ public:
virtual void get_export_options(List<ExportOption> *r_options) {
- r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "graphics/xr_mode", PROPERTY_HINT_ENUM, "Regular,Oculus Mobile VR"), 0));
- r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "graphics/degrees_of_freedom", PROPERTY_HINT_ENUM, "None,3DOF and 6DOF,6DOF"), 0));
r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "graphics/32_bits_framebuffer"), true));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "xr_features/xr_mode", PROPERTY_HINT_ENUM, "Regular,Oculus Mobile VR"), 0));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "xr_features/degrees_of_freedom", PROPERTY_HINT_ENUM, "None,3DOF and 6DOF,6DOF"), 0));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "xr_features/hand_tracking", PROPERTY_HINT_ENUM, "None,Optional,Required"), 0));
r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "one_click_deploy/clear_previous_install"), false));
- r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "custom_package/debug", PROPERTY_HINT_GLOBAL_FILE, "*.apk"), ""));
- r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "custom_package/release", PROPERTY_HINT_GLOBAL_FILE, "*.apk"), ""));
- r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "custom_package/use_custom_build"), false));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "custom_template/debug", PROPERTY_HINT_GLOBAL_FILE, "*.apk"), ""));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "custom_template/release", PROPERTY_HINT_GLOBAL_FILE, "*.apk"), ""));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "custom_template/use_custom_build"), false));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "command_line/extra_args"), ""));
r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "version/code", PROPERTY_HINT_RANGE, "1,4096,1,or_greater"), 1));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "version/name"), "1.0"));
@@ -1315,11 +1402,9 @@ public:
r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "screen/support_large"), true));
r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "screen/support_xlarge"), true));
r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "screen/opengl_debug"), false));
-
- for (uint64_t i = 0; i < sizeof(launcher_icons) / sizeof(launcher_icons[0]); ++i) {
- r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, launcher_icons[i].option_id, PROPERTY_HINT_FILE, "*.png"), ""));
- }
-
+ r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, launcher_icon_option, PROPERTY_HINT_FILE, "*.png"), ""));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, launcher_adaptive_icon_foreground_option, PROPERTY_HINT_FILE, "*.png"), ""));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, launcher_adaptive_icon_background_option, PROPERTY_HINT_FILE, "*.png"), ""));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "keystore/debug", PROPERTY_HINT_GLOBAL_FILE, "*.keystore"), ""));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "keystore/debug_user"), ""));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "keystore/debug_password"), ""));
@@ -1577,29 +1662,34 @@ public:
virtual bool can_export(const Ref<EditorExportPreset> &p_preset, String &r_error, bool &r_missing_templates) const {
String err;
+ bool valid = false;
- if (!bool(p_preset->get("custom_package/use_custom_build"))) {
+ // Look for export templates (first official, and if defined custom templates).
- r_missing_templates = find_export_template("android_debug.apk") == String() || find_export_template("android_release.apk") == String();
+ if (!bool(p_preset->get("custom_template/use_custom_build"))) {
+ bool dvalid = exists_export_template("android_debug.apk", &err);
+ bool rvalid = exists_export_template("android_release.apk", &err);
- if (p_preset->get("custom_package/debug") != "") {
- if (FileAccess::exists(p_preset->get("custom_package/debug"))) {
- r_missing_templates = false;
- } else {
+ if (p_preset->get("custom_template/debug") != "") {
+ dvalid = FileAccess::exists(p_preset->get("custom_template/debug"));
+ if (!dvalid) {
err += TTR("Custom debug template not found.") + "\n";
}
}
-
- if (p_preset->get("custom_package/release") != "") {
- if (FileAccess::exists(p_preset->get("custom_package/release"))) {
- r_missing_templates = false;
- } else {
+ if (p_preset->get("custom_template/release") != "") {
+ rvalid = FileAccess::exists(p_preset->get("custom_template/release"));
+ if (!rvalid) {
err += TTR("Custom release template not found.") + "\n";
}
}
+
+ valid = dvalid || rvalid;
+ } else {
+ valid = exists_export_template("android_source.zip", &err);
}
+ r_missing_templates = !valid;
- bool valid = !r_missing_templates;
+ // Validate the rest of the configuration.
String adb = EditorSettings::get_singleton()->get("export/android/adb");
@@ -1628,7 +1718,7 @@ public:
}
}
- if (bool(p_preset->get("custom_package/use_custom_build"))) {
+ if (bool(p_preset->get("custom_template/use_custom_build"))) {
String sdk_path = EditorSettings::get_singleton()->get("export/android/custom_build_sdk_path");
if (sdk_path == "") {
err += TTR("Custom build requires a valid Android SDK path in Editor Settings.") + "\n";
@@ -1912,7 +2002,7 @@ public:
}
} else if (l.strip_edges().begins_with("<application")) {
- String last_tag = "android:icon=\"@drawable/icon\"";
+ String last_tag = "android:icon=\"@mipmap/icon\"";
int last_tag_pos = l.find(last_tag);
if (last_tag_pos == -1) {
ERR_PRINTS("Not adding application attributes as the expected tag was not found in '<application': " + last_tag);
@@ -1949,7 +2039,7 @@ public:
EditorProgress ep("export", "Exporting for Android", 105, true);
- if (bool(p_preset->get("custom_package/use_custom_build"))) { //custom build
+ if (bool(p_preset->get("custom_template/use_custom_build"))) { //custom build
//re-generate build.gradle and AndroidManifest.xml
{ //test that installed build version is alright
@@ -2017,9 +2107,9 @@ public:
} else {
if (p_debug)
- src_apk = p_preset->get("custom_package/debug");
+ src_apk = p_preset->get("custom_template/debug");
else
- src_apk = p_preset->get("custom_package/release");
+ src_apk = p_preset->get("custom_template/release");
src_apk = src_apk.strip_edges();
if (src_apk == "") {
@@ -2091,6 +2181,35 @@ public:
Vector<String> enabled_abis = get_enabled_abis(p_preset);
+ String project_icon_path = ProjectSettings::get_singleton()->get("application/config/icon");
+
+ // Prepare images to be resized for the icons. If some image ends up being uninitialized, the default image from the export template will be used.
+ Ref<Image> launcher_icon_image;
+ Ref<Image> launcher_adaptive_icon_foreground_image;
+ Ref<Image> launcher_adaptive_icon_background_image;
+
+ launcher_icon_image.instance();
+ launcher_adaptive_icon_foreground_image.instance();
+ launcher_adaptive_icon_background_image.instance();
+
+ // Regular icon: user selection -> project icon -> default.
+ String path = static_cast<String>(p_preset->get(launcher_icon_option)).strip_edges();
+ if (path.empty() || ImageLoader::load_image(path, launcher_icon_image) != OK) {
+ ImageLoader::load_image(project_icon_path, launcher_icon_image);
+ }
+
+ // 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();
+ if (path.empty() || ImageLoader::load_image(path, launcher_adaptive_icon_foreground_image) != OK) {
+ launcher_adaptive_icon_foreground_image = launcher_icon_image;
+ }
+
+ // Adaptive background: user selection -> default.
+ path = static_cast<String>(p_preset->get(launcher_adaptive_icon_background_option)).strip_edges();
+ if (!path.empty()) {
+ ImageLoader::load_image(path, launcher_adaptive_icon_background_image);
+ }
+
while (ret == UNZ_OK) {
//get filename
@@ -2113,41 +2232,22 @@ public:
//write
if (file == "AndroidManifest.xml") {
-
_fix_manifest(p_preset, data, p_flags & (DEBUG_FLAG_DUMB_CLIENT | DEBUG_FLAG_REMOTE_DEBUG));
}
if (file == "resources.arsc") {
-
_fix_resources(p_preset, data);
}
- if (file == "res/drawable-nodpi-v4/icon.png") {
- bool found = false;
- for (uint64_t i = 0; i < sizeof(launcher_icons) / sizeof(launcher_icons[0]); ++i) {
- String icon_path = String(p_preset->get(launcher_icons[i].option_id)).strip_edges();
- if (icon_path != "" && icon_path.ends_with(".png")) {
- FileAccess *f = FileAccess::open(icon_path, FileAccess::READ);
- if (f) {
- data.resize(f->get_len());
- f->get_buffer(data.ptrw(), data.size());
- memdelete(f);
- found = true;
- break;
- }
- }
+ for (int i = 0; i < icon_densities_count; ++i) {
+ if (launcher_icon_image.is_valid() && !launcher_icon_image->empty()) {
+ _process_launcher_icons(file, launcher_icon_image, launcher_icons[i], data);
}
- if (!found) {
-
- String appicon = ProjectSettings::get_singleton()->get("application/config/icon");
- if (appicon != "" && appicon.ends_with(".png")) {
- FileAccess *f = FileAccess::open(appicon, FileAccess::READ);
- if (f) {
- data.resize(f->get_len());
- f->get_buffer(data.ptrw(), data.size());
- memdelete(f);
- }
- }
+ if (launcher_adaptive_icon_foreground_image.is_valid() && !launcher_adaptive_icon_foreground_image->empty()) {
+ _process_launcher_icons(file, launcher_adaptive_icon_foreground_image, launcher_adaptive_icon_foregrounds[i], data);
+ }
+ if (launcher_adaptive_icon_background_image.is_valid() && !launcher_adaptive_icon_background_image->empty()) {
+ _process_launcher_icons(file, launcher_adaptive_icon_background_image, launcher_adaptive_icon_backgrounds[i], data);
}
}
@@ -2246,20 +2346,7 @@ public:
}
}
- if (!err) {
- APKExportData ed;
- ed.ep = &ep;
- ed.apk = unaligned_apk;
- for (uint64_t i = 0; i < sizeof(launcher_icons) / sizeof(launcher_icons[0]); ++i) {
- String icon_path = String(p_preset->get(launcher_icons[i].option_id)).strip_edges();
- if (icon_path != "" && icon_path.ends_with(".png") && FileAccess::exists(icon_path)) {
- Vector<uint8_t> data = FileAccess::get_file_as_array(icon_path);
- store_in_apk(&ed, launcher_icons[i].export_path, data);
- }
- }
- }
-
- int xr_mode_index = p_preset->get("graphics/xr_mode");
+ int xr_mode_index = p_preset->get("xr_features/xr_mode");
if (xr_mode_index == 1 /* XRMode.OVR */) {
cl.push_back("--xr_mode_ovr");
} else {
diff --git a/platform/android/java/app/AndroidManifest.xml b/platform/android/java/app/AndroidManifest.xml
index ba01ec313b..7e9ce70d80 100644
--- a/platform/android/java/app/AndroidManifest.xml
+++ b/platform/android/java/app/AndroidManifest.xml
@@ -27,7 +27,7 @@
<!-- Any tag in this line after android:icon will be erased when doing custom builds. -->
<!-- If you want to add tags manually, do before it. -->
<!-- WARNING: This should stay on a single line until the parsing code is improved. See GH-32414. -->
- <application android:label="@string/godot_project_name_string" android:allowBackup="false" tools:ignore="GoogleAppIndexingWarning" android:icon="@drawable/icon" >
+ <application android:label="@string/godot_project_name_string" android:allowBackup="false" tools:ignore="GoogleAppIndexingWarning" android:icon="@mipmap/icon" >
<!-- 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. -->
diff --git a/platform/android/java/lib/AndroidManifest.xml b/platform/android/java/lib/AndroidManifest.xml
index 517fc403b2..b133585f99 100644
--- a/platform/android/java/lib/AndroidManifest.xml
+++ b/platform/android/java/lib/AndroidManifest.xml
@@ -11,7 +11,7 @@
</application>
<instrumentation
- android:icon="@drawable/icon"
+ android:icon="@mipmap/icon"
android:label="@string/godot_project_name_string"
android:name=".GodotInstrumentation"
android:targetPackage="org.godotengine.godot" />
diff --git a/platform/android/java/lib/res/drawable-nodpi/icon.png b/platform/android/java/lib/res/drawable-nodpi/icon.png
deleted file mode 100644
index 6ad9b43117..0000000000
--- a/platform/android/java/lib/res/drawable-nodpi/icon.png
+++ /dev/null
Binary files differ
diff --git a/platform/android/java/lib/res/mipmap-anydpi-v26/icon.xml b/platform/android/java/lib/res/mipmap-anydpi-v26/icon.xml
new file mode 100644
index 0000000000..1ed4037035
--- /dev/null
+++ b/platform/android/java/lib/res/mipmap-anydpi-v26/icon.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
+ <background android:drawable="@mipmap/icon_background"/>
+ <foreground android:drawable="@mipmap/icon_foreground"/>
+</adaptive-icon> \ No newline at end of file
diff --git a/platform/android/java/lib/res/mipmap-hdpi/icon.png b/platform/android/java/lib/res/mipmap-hdpi/icon.png
new file mode 100644
index 0000000000..cc6e113e89
--- /dev/null
+++ b/platform/android/java/lib/res/mipmap-hdpi/icon.png
Binary files differ
diff --git a/platform/android/java/lib/res/mipmap-hdpi/icon_background.png b/platform/android/java/lib/res/mipmap-hdpi/icon_background.png
new file mode 100644
index 0000000000..78445c0181
--- /dev/null
+++ b/platform/android/java/lib/res/mipmap-hdpi/icon_background.png
Binary files differ
diff --git a/platform/android/java/lib/res/mipmap-hdpi/icon_foreground.png b/platform/android/java/lib/res/mipmap-hdpi/icon_foreground.png
new file mode 100644
index 0000000000..75e409ff74
--- /dev/null
+++ b/platform/android/java/lib/res/mipmap-hdpi/icon_foreground.png
Binary files differ
diff --git a/platform/android/java/lib/res/mipmap-mdpi/icon.png b/platform/android/java/lib/res/mipmap-mdpi/icon.png
new file mode 100644
index 0000000000..e1968fe142
--- /dev/null
+++ b/platform/android/java/lib/res/mipmap-mdpi/icon.png
Binary files differ
diff --git a/platform/android/java/lib/res/mipmap-mdpi/icon_background.png b/platform/android/java/lib/res/mipmap-mdpi/icon_background.png
new file mode 100644
index 0000000000..5813f751ed
--- /dev/null
+++ b/platform/android/java/lib/res/mipmap-mdpi/icon_background.png
Binary files differ
diff --git a/platform/android/java/lib/res/mipmap-mdpi/icon_foreground.png b/platform/android/java/lib/res/mipmap-mdpi/icon_foreground.png
new file mode 100644
index 0000000000..982b69be1e
--- /dev/null
+++ b/platform/android/java/lib/res/mipmap-mdpi/icon_foreground.png
Binary files differ
diff --git a/platform/android/java/lib/res/mipmap-xhdpi/icon.png b/platform/android/java/lib/res/mipmap-xhdpi/icon.png
new file mode 100644
index 0000000000..9281d8da48
--- /dev/null
+++ b/platform/android/java/lib/res/mipmap-xhdpi/icon.png
Binary files differ
diff --git a/platform/android/java/lib/res/mipmap-xhdpi/icon_background.png b/platform/android/java/lib/res/mipmap-xhdpi/icon_background.png
new file mode 100644
index 0000000000..4269c822a7
--- /dev/null
+++ b/platform/android/java/lib/res/mipmap-xhdpi/icon_background.png
Binary files differ
diff --git a/platform/android/java/lib/res/mipmap-xhdpi/icon_foreground.png b/platform/android/java/lib/res/mipmap-xhdpi/icon_foreground.png
new file mode 100644
index 0000000000..726b267ad6
--- /dev/null
+++ b/platform/android/java/lib/res/mipmap-xhdpi/icon_foreground.png
Binary files differ
diff --git a/platform/android/java/lib/res/mipmap-xxhdpi/icon.png b/platform/android/java/lib/res/mipmap-xxhdpi/icon.png
new file mode 100644
index 0000000000..7a6b67d273
--- /dev/null
+++ b/platform/android/java/lib/res/mipmap-xxhdpi/icon.png
Binary files differ
diff --git a/platform/android/java/lib/res/mipmap-xxhdpi/icon_background.png b/platform/android/java/lib/res/mipmap-xxhdpi/icon_background.png
new file mode 100644
index 0000000000..5e8b518d17
--- /dev/null
+++ b/platform/android/java/lib/res/mipmap-xxhdpi/icon_background.png
Binary files differ
diff --git a/platform/android/java/lib/res/mipmap-xxhdpi/icon_foreground.png b/platform/android/java/lib/res/mipmap-xxhdpi/icon_foreground.png
new file mode 100644
index 0000000000..b0c727f74c
--- /dev/null
+++ b/platform/android/java/lib/res/mipmap-xxhdpi/icon_foreground.png
Binary files differ
diff --git a/platform/android/java/lib/res/mipmap-xxxhdpi/icon.png b/platform/android/java/lib/res/mipmap-xxxhdpi/icon.png
new file mode 100644
index 0000000000..0881245802
--- /dev/null
+++ b/platform/android/java/lib/res/mipmap-xxxhdpi/icon.png
Binary files differ
diff --git a/platform/android/java/lib/res/mipmap-xxxhdpi/icon_background.png b/platform/android/java/lib/res/mipmap-xxxhdpi/icon_background.png
new file mode 100644
index 0000000000..004b6fd508
--- /dev/null
+++ b/platform/android/java/lib/res/mipmap-xxxhdpi/icon_background.png
Binary files differ
diff --git a/platform/android/java/lib/res/mipmap-xxxhdpi/icon_foreground.png b/platform/android/java/lib/res/mipmap-xxxhdpi/icon_foreground.png
new file mode 100644
index 0000000000..72e6f92b6e
--- /dev/null
+++ b/platform/android/java/lib/res/mipmap-xxxhdpi/icon_foreground.png
Binary files differ
diff --git a/platform/android/java/lib/res/mipmap/icon.png b/platform/android/java/lib/res/mipmap/icon.png
new file mode 100644
index 0000000000..0881245802
--- /dev/null
+++ b/platform/android/java/lib/res/mipmap/icon.png
Binary files differ
diff --git a/platform/android/java/lib/res/mipmap/icon_background.png b/platform/android/java/lib/res/mipmap/icon_background.png
new file mode 100644
index 0000000000..5813f751ed
--- /dev/null
+++ b/platform/android/java/lib/res/mipmap/icon_background.png
Binary files differ
diff --git a/platform/android/java/lib/res/mipmap/icon_foreground.png b/platform/android/java/lib/res/mipmap/icon_foreground.png
new file mode 100644
index 0000000000..982b69be1e
--- /dev/null
+++ b/platform/android/java/lib/res/mipmap/icon_foreground.png
Binary files differ
diff --git a/platform/android/java/lib/src/org/godotengine/godot/GodotLib.java b/platform/android/java/lib/src/org/godotengine/godot/GodotLib.java
index 8447af10e4..e0b46673ba 100644
--- a/platform/android/java/lib/src/org/godotengine/godot/GodotLib.java
+++ b/platform/android/java/lib/src/org/godotengine/godot/GodotLib.java
@@ -100,6 +100,16 @@ public class GodotLib {
public static native void hover(int type, int x, int y);
/**
+ * Forward double_tap events from the main thread to the GL thread.
+ */
+ public static native void doubletap(int x, int y);
+
+ /**
+ * Forward scroll events from the main thread to the GL thread.
+ */
+ public static native void scroll(int x, int y);
+
+ /**
* Forward accelerometer sensor events from the main thread to the GL thread.
* @see android.hardware.SensorEventListener#onSensorChanged(SensorEvent)
*/
diff --git a/platform/android/java/lib/src/org/godotengine/godot/GodotView.java b/platform/android/java/lib/src/org/godotengine/godot/GodotView.java
index 78f3763d84..f938583082 100644
--- a/platform/android/java/lib/src/org/godotengine/godot/GodotView.java
+++ b/platform/android/java/lib/src/org/godotengine/godot/GodotView.java
@@ -32,8 +32,10 @@ package org.godotengine.godot;
import android.annotation.SuppressLint;
import android.graphics.PixelFormat;
import android.opengl.GLSurfaceView;
+import android.view.GestureDetector;
import android.view.KeyEvent;
import android.view.MotionEvent;
+import org.godotengine.godot.input.GodotGestureHandler;
import org.godotengine.godot.input.GodotInputHandler;
import org.godotengine.godot.utils.GLUtils;
import org.godotengine.godot.xr.XRMode;
@@ -68,6 +70,7 @@ public class GodotView extends GLSurfaceView {
private final Godot activity;
private final GodotInputHandler inputHandler;
+ private final GestureDetector detector;
private final GodotRenderer godotRenderer;
public GodotView(Godot activity, XRMode xrMode, boolean p_use_gl3, boolean p_use_32_bits, boolean p_use_debug_opengl) {
@@ -78,6 +81,7 @@ public class GodotView extends GLSurfaceView {
this.activity = activity;
this.inputHandler = new GodotInputHandler(this);
+ this.detector = new GestureDetector(activity, new GodotGestureHandler(this));
this.godotRenderer = new GodotRenderer();
init(xrMode, false, 16, 0);
}
@@ -90,6 +94,7 @@ public class GodotView extends GLSurfaceView {
@Override
public boolean onTouchEvent(MotionEvent event) {
super.onTouchEvent(event);
+ this.detector.onTouchEvent(event);
return activity.gotTouchEvent(event);
}
diff --git a/platform/android/java/lib/src/org/godotengine/godot/input/GodotGestureHandler.java b/platform/android/java/lib/src/org/godotengine/godot/input/GodotGestureHandler.java
new file mode 100644
index 0000000000..1a38a9c3d2
--- /dev/null
+++ b/platform/android/java/lib/src/org/godotengine/godot/input/GodotGestureHandler.java
@@ -0,0 +1,106 @@
+/*************************************************************************/
+/* GodotGestureHandler.java */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2020 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.input;
+
+import android.util.Log;
+import android.view.GestureDetector;
+import android.view.MotionEvent;
+import org.godotengine.godot.GodotLib;
+import org.godotengine.godot.GodotView;
+
+/**
+ * Handles gesture input related events for the {@link GodotView} view.
+ * https://developer.android.com/reference/android/view/GestureDetector.SimpleOnGestureListener
+ */
+public class GodotGestureHandler extends GestureDetector.SimpleOnGestureListener {
+
+ private final GodotView godotView;
+
+ public GodotGestureHandler(GodotView godotView) {
+ this.godotView = godotView;
+ }
+
+ private void queueEvent(Runnable task) {
+ godotView.queueEvent(task);
+ }
+
+ @Override
+ public boolean onDown(MotionEvent event) {
+ super.onDown(event);
+ //Log.i("GodotGesture", "onDown");
+ return true;
+ }
+
+ @Override
+ public boolean onSingleTapConfirmed(MotionEvent event) {
+ super.onSingleTapConfirmed(event);
+ return true;
+ }
+
+ @Override
+ public void onLongPress(MotionEvent event) {
+ //Log.i("GodotGesture", "onLongPress");
+ }
+
+ @Override
+ public boolean onDoubleTap(MotionEvent event) {
+ //Log.i("GodotGesture", "onDoubleTap");
+ final int x = Math.round(event.getX());
+ final int y = Math.round(event.getY());
+ queueEvent(new Runnable() {
+ @Override
+ public void run() {
+ GodotLib.doubletap(x, y);
+ }
+ });
+ return true;
+ }
+
+ @Override
+ public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
+ //Log.i("GodotGesture", "onScroll");
+ final int x = Math.round(distanceX);
+ final int y = Math.round(distanceY);
+ queueEvent(new Runnable() {
+ @Override
+ public void run() {
+ GodotLib.scroll(x, y);
+ }
+ });
+ return true;
+ }
+
+ @Override
+ public boolean onFling(MotionEvent event1, MotionEvent event2, float velocityX, float velocityY) {
+ //Log.i("GodotGesture", "onFling");
+ return true;
+ }
+}
diff --git a/platform/android/java_godot_lib_jni.cpp b/platform/android/java_godot_lib_jni.cpp
index 0a32f4423b..858ff89cbc 100644
--- a/platform/android/java_godot_lib_jni.cpp
+++ b/platform/android/java_godot_lib_jni.cpp
@@ -835,6 +835,20 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_hover(JNIEnv *env, jo
os_android->process_hover(p_type, Point2(p_x, p_y));
}
+JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_doubletap(JNIEnv *env, jobject obj, jint p_x, jint p_y) {
+ if (step == 0)
+ return;
+
+ os_android->process_double_tap(Point2(p_x, p_y));
+}
+
+JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_scroll(JNIEnv *env, jobject obj, jint p_x, jint p_y) {
+ if (step == 0)
+ return;
+
+ os_android->process_scroll(Point2(p_x, p_y));
+}
+
/*
* Android Key codes.
*/
diff --git a/platform/android/java_godot_lib_jni.h b/platform/android/java_godot_lib_jni.h
index 8c18c52d2b..71d4547f65 100644
--- a/platform/android/java_godot_lib_jni.h
+++ b/platform/android/java_godot_lib_jni.h
@@ -46,6 +46,8 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_step(JNIEnv *env, job
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_back(JNIEnv *env, jobject obj);
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_touch(JNIEnv *env, jobject obj, jint ev, jint pointer, jint count, jintArray positions);
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_hover(JNIEnv *env, jobject obj, jint p_type, jint p_x, jint p_y);
+JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_doubletap(JNIEnv *env, jobject obj, jint p_x, jint p_y);
+JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_scroll(JNIEnv *env, jobject obj, jint p_x, jint p_y);
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_key(JNIEnv *env, jobject obj, jint p_scancode, jint p_unicode_char, jboolean p_pressed);
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_joybutton(JNIEnv *env, jobject obj, jint p_device, jint p_button, jboolean p_pressed);
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_joyaxis(JNIEnv *env, jobject obj, jint p_device, jint p_axis, jfloat p_value);
diff --git a/platform/android/os_android.cpp b/platform/android/os_android.cpp
index 4c560273e8..bbea5e3699 100644
--- a/platform/android/os_android.cpp
+++ b/platform/android/os_android.cpp
@@ -502,6 +502,26 @@ void OS_Android::process_hover(int p_type, Point2 p_pos) {
}
}
+void OS_Android::process_double_tap(Point2 p_pos) {
+ Ref<InputEventMouseButton> ev;
+ ev.instance();
+ ev->set_position(p_pos);
+ ev->set_global_position(p_pos);
+ ev->set_pressed(true);
+ ev->set_doubleclick(true);
+ ev->set_button_index(1);
+ input->parse_input_event(ev);
+}
+
+void OS_Android::process_scroll(Point2 p_pos) {
+ Ref<InputEventPanGesture> ev;
+ ev.instance();
+ ev->set_position(p_pos);
+ ev->set_delta(p_pos - scroll_prev_pos);
+ input->parse_input_event(ev);
+ scroll_prev_pos = p_pos;
+}
+
void OS_Android::process_accelerometer(const Vector3 &p_accelerometer) {
input->set_accelerometer(p_accelerometer);
diff --git a/platform/android/os_android.h b/platform/android/os_android.h
index 5ac50ddef2..1cf64a2e84 100644
--- a/platform/android/os_android.h
+++ b/platform/android/os_android.h
@@ -70,6 +70,7 @@ public:
private:
Vector<TouchPos> touch;
Point2 hover_prev_pos; // needed to calculate the relative position on hover events
+ Point2 scroll_prev_pos; // needed to calculate the relative position on scroll events
bool use_gl2;
bool use_apk_expansion;
@@ -187,6 +188,8 @@ public:
void process_gyroscope(const Vector3 &p_gyroscope);
void process_touch(int p_what, int p_pointer, const Vector<TouchPos> &p_points);
void process_hover(int p_type, Point2 p_pos);
+ void process_double_tap(Point2 p_pos);
+ void process_scroll(Point2 p_pos);
void process_joy_event(JoypadEvent p_event);
void process_event(Ref<InputEvent> p_event);
void init_video_mode(int p_video_width, int p_video_height);
diff --git a/platform/haiku/detect.py b/platform/haiku/detect.py
index 2a3e165069..dd72294816 100644
--- a/platform/haiku/detect.py
+++ b/platform/haiku/detect.py
@@ -95,7 +95,7 @@ def configure(env):
if not env['builtin_enet']:
env.ParseConfig('pkg-config libenet --cflags --libs')
- if not env['builtin_squish'] and env['tools']:
+ if not env['builtin_squish']:
env.ParseConfig('pkg-config libsquish --cflags --libs')
if not env['builtin_zstd']:
diff --git a/platform/iphone/export/export.cpp b/platform/iphone/export/export.cpp
index c80370847d..b606d570c2 100644
--- a/platform/iphone/export/export.cpp
+++ b/platform/iphone/export/export.cpp
@@ -206,8 +206,8 @@ static const LoadingScreenInfo loading_screen_infos[] = {
void EditorExportPlatformIOS::get_export_options(List<ExportOption> *r_options) {
- r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "custom_package/debug", PROPERTY_HINT_GLOBAL_FILE, "*.zip"), ""));
- r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "custom_package/release", PROPERTY_HINT_GLOBAL_FILE, "*.zip"), ""));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "custom_template/debug", PROPERTY_HINT_GLOBAL_FILE, "*.zip"), ""));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "custom_template/release", PROPERTY_HINT_GLOBAL_FILE, "*.zip"), ""));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/app_store_team_id"), ""));
@@ -848,9 +848,9 @@ Error EditorExportPlatformIOS::export_project(const Ref<EditorExportPreset> &p_p
ERR_FAIL_COND_V_MSG(team_id.length() == 0, ERR_CANT_OPEN, "App Store Team ID not specified - cannot configure the project.");
if (p_debug)
- src_pkg_name = p_preset->get("custom_package/debug");
+ src_pkg_name = p_preset->get("custom_template/debug");
else
- src_pkg_name = p_preset->get("custom_package/release");
+ src_pkg_name = p_preset->get("custom_template/release");
if (src_pkg_name == "") {
String err;
@@ -1156,25 +1156,30 @@ Error EditorExportPlatformIOS::export_project(const Ref<EditorExportPreset> &p_p
bool EditorExportPlatformIOS::can_export(const Ref<EditorExportPreset> &p_preset, String &r_error, bool &r_missing_templates) const {
String err;
- r_missing_templates = find_export_template("iphone.zip") == String();
+ bool valid = false;
- if (p_preset->get("custom_package/debug") != "") {
- if (FileAccess::exists(p_preset->get("custom_package/debug"))) {
- r_missing_templates = false;
- } else {
+ // Look for export templates (first official, and if defined custom templates).
+
+ bool dvalid = exists_export_template("iphone.zip", &err);
+ bool rvalid = dvalid; // Both in the same ZIP.
+
+ if (p_preset->get("custom_template/debug") != "") {
+ dvalid = FileAccess::exists(p_preset->get("custom_template/debug"));
+ if (!dvalid) {
err += TTR("Custom debug template not found.") + "\n";
}
}
-
- if (p_preset->get("custom_package/release") != "") {
- if (FileAccess::exists(p_preset->get("custom_package/release"))) {
- r_missing_templates = false;
- } else {
+ if (p_preset->get("custom_template/release") != "") {
+ rvalid = FileAccess::exists(p_preset->get("custom_template/release"));
+ if (!rvalid) {
err += TTR("Custom release template not found.") + "\n";
}
}
- bool valid = !r_missing_templates;
+ valid = dvalid || rvalid;
+ r_missing_templates = !valid;
+
+ // Validate the rest of the configuration.
String team_id = p_preset->get("application/app_store_team_id");
if (team_id.length() == 0) {
diff --git a/platform/javascript/export/export.cpp b/platform/javascript/export/export.cpp
index bbdf6a1f57..9b93d4f140 100644
--- a/platform/javascript/export/export.cpp
+++ b/platform/javascript/export/export.cpp
@@ -87,16 +87,22 @@ public:
String filepath = EditorSettings::get_singleton()->get_cache_dir().plus_file("tmp_js_export");
String basereq = "/tmp_js_export";
+ String ctype = "";
if (req[1] == basereq + ".html") {
filepath += ".html";
+ ctype = "text/html";
} else if (req[1] == basereq + ".js") {
filepath += ".js";
+ ctype = "application/javascript";
} else if (req[1] == basereq + ".pck") {
filepath += ".pck";
+ ctype = "application/octet-stream";
} else if (req[1] == basereq + ".png") {
filepath += ".png";
+ ctype = "image/png";
} else if (req[1] == basereq + ".wasm") {
filepath += ".wasm";
+ ctype = "application/wasm";
} else {
String s = "HTTP/1.1 404 Not Found\r\n";
s += "Connection: Close\r\n";
@@ -109,10 +115,14 @@ public:
ERR_FAIL_COND(!f);
String s = "HTTP/1.1 200 OK\r\n";
s += "Connection: Close\r\n";
+ s += "Content-Type: " + ctype + "\r\n";
s += "\r\n";
CharString cs = s.utf8();
Error err = connection->put_data((const uint8_t *)cs.get_data(), cs.size() - 1);
- ERR_FAIL_COND(err != OK);
+ if (err != OK) {
+ memdelete(f);
+ ERR_FAIL();
+ }
while (true) {
uint8_t bytes[4096];
@@ -121,8 +131,12 @@ public:
break;
}
err = connection->put_data(bytes, read);
- ERR_FAIL_COND(err != OK);
+ if (err != OK) {
+ memdelete(f);
+ ERR_FAIL();
+ }
}
+ memdelete(f);
}
void poll() {
@@ -288,32 +302,32 @@ Ref<Texture> EditorExportPlatformJavaScript::get_logo() const {
bool EditorExportPlatformJavaScript::can_export(const Ref<EditorExportPreset> &p_preset, String &r_error, bool &r_missing_templates) const {
- bool valid = false;
String err;
+ bool valid = false;
- if (find_export_template(EXPORT_TEMPLATE_WEBASSEMBLY_RELEASE) != "")
- valid = true;
- else if (find_export_template(EXPORT_TEMPLATE_WEBASSEMBLY_DEBUG) != "")
- valid = true;
+ // Look for export templates (first official, and if defined custom templates).
+
+ bool dvalid = exists_export_template(EXPORT_TEMPLATE_WEBASSEMBLY_DEBUG, &err);
+ bool rvalid = exists_export_template(EXPORT_TEMPLATE_WEBASSEMBLY_RELEASE, &err);
if (p_preset->get("custom_template/debug") != "") {
- if (FileAccess::exists(p_preset->get("custom_template/debug"))) {
- valid = true;
- } else {
+ dvalid = FileAccess::exists(p_preset->get("custom_template/debug"));
+ if (!dvalid) {
err += TTR("Custom debug template not found.") + "\n";
}
}
-
if (p_preset->get("custom_template/release") != "") {
- if (FileAccess::exists(p_preset->get("custom_template/release"))) {
- valid = true;
- } else {
+ rvalid = FileAccess::exists(p_preset->get("custom_template/release"));
+ if (!rvalid) {
err += TTR("Custom release template not found.") + "\n";
}
}
+ valid = dvalid || rvalid;
r_missing_templates = !valid;
+ // Validate the rest of the configuration.
+
if (p_preset->get("vram_texture_compression/for_mobile")) {
String etc_error = test_etc2();
if (etc_error != String()) {
diff --git a/platform/osx/export/export.cpp b/platform/osx/export/export.cpp
index dd98a98996..cf38664022 100644
--- a/platform/osx/export/export.cpp
+++ b/platform/osx/export/export.cpp
@@ -118,8 +118,8 @@ void EditorExportPlatformOSX::get_preset_features(const Ref<EditorExportPreset>
void EditorExportPlatformOSX::get_export_options(List<ExportOption> *r_options) {
- r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "custom_package/debug", PROPERTY_HINT_GLOBAL_FILE, "*.zip"), ""));
- r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "custom_package/release", PROPERTY_HINT_GLOBAL_FILE, "*.zip"), ""));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "custom_template/debug", PROPERTY_HINT_GLOBAL_FILE, "*.zip"), ""));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "custom_template/release", PROPERTY_HINT_GLOBAL_FILE, "*.zip"), ""));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/name", PROPERTY_HINT_PLACEHOLDER_TEXT, "Game Name"), ""));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/info"), "Made with Godot Engine"));
@@ -459,9 +459,9 @@ Error EditorExportPlatformOSX::export_project(const Ref<EditorExportPreset> &p_p
EditorProgress ep("export", "Exporting for OSX", 3, true);
if (p_debug)
- src_pkg_name = p_preset->get("custom_package/debug");
+ src_pkg_name = p_preset->get("custom_template/debug");
else
- src_pkg_name = p_preset->get("custom_package/release");
+ src_pkg_name = p_preset->get("custom_template/release");
if (src_pkg_name == "") {
String err;
@@ -502,6 +502,8 @@ Error EditorExportPlatformOSX::export_project(const Ref<EditorExportPreset> &p_p
else
pkg_name = "Unnamed";
+ String pkg_name_safe = OS::get_singleton()->get_safe_dir_name(pkg_name);
+
Error err = OK;
String tmp_app_path_name = "";
zlib_filefunc_def io2 = io;
@@ -509,12 +511,13 @@ Error EditorExportPlatformOSX::export_project(const Ref<EditorExportPreset> &p_p
io2.opaque = &dst_f;
zipFile dst_pkg_zip = NULL;
+ DirAccess *tmp_app_path = NULL;
String export_format = use_dmg() && p_path.ends_with("dmg") ? "dmg" : "zip";
if (export_format == "dmg") {
// We're on OSX so we can export to DMG, but first we create our application bundle
tmp_app_path_name = EditorSettings::get_singleton()->get_cache_dir().plus_file(pkg_name + ".app");
print_line("Exporting to " + tmp_app_path_name);
- DirAccess *tmp_app_path = DirAccess::create_for_path(tmp_app_path_name);
+ tmp_app_path = DirAccess::create_for_path(tmp_app_path_name);
if (!tmp_app_path) {
err = ERR_CANT_CREATE;
}
@@ -611,25 +614,45 @@ Error EditorExportPlatformOSX::export_project(const Ref<EditorExportPreset> &p_p
}
if (data.size() > 0) {
+
+ if (file.find("/data.mono.osx.64.release_debug/") != -1) {
+ if (!p_debug) {
+ ret = unzGoToNextFile(src_pkg_zip);
+ continue; //skip
+ }
+ file = file.replace("/data.mono.osx.64.release_debug/", "/data_" + pkg_name_safe + "/");
+ }
+ 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_safe + "/");
+ }
+
print_line("ADDING: " + file + " size: " + itos(data.size()));
total_size += data.size();
if (export_format == "dmg") {
// write it into our application bundle
file = tmp_app_path_name.plus_file(file);
-
- // write the file, need to add chmod
- FileAccess *f = FileAccess::open(file, FileAccess::WRITE);
- if (f) {
- f->store_buffer(data.ptr(), data.size());
- f->close();
- if (is_execute) {
- // Chmod with 0755 if the file is executable
- FileAccess::set_unix_permissions(file, 0755);
+ if (err == OK) {
+ err = tmp_app_path->make_dir_recursive(file.get_base_dir());
+ }
+ if (err == OK) {
+ // write the file, need to add chmod
+ FileAccess *f = FileAccess::open(file, FileAccess::WRITE);
+ if (f) {
+ f->store_buffer(data.ptr(), data.size());
+ f->close();
+ if (is_execute) {
+ // Chmod with 0755 if the file is executable
+ FileAccess::set_unix_permissions(file, 0755);
+ }
+ memdelete(f);
+ } else {
+ err = ERR_CANT_CREATE;
}
- memdelete(f);
- } else {
- err = ERR_CANT_CREATE;
}
} else {
// add it to our zip file
@@ -796,33 +819,32 @@ Error EditorExportPlatformOSX::export_project(const Ref<EditorExportPreset> &p_p
bool EditorExportPlatformOSX::can_export(const Ref<EditorExportPreset> &p_preset, String &r_error, bool &r_missing_templates) const {
- bool valid = false;
String err;
+ bool valid = false;
- if (exists_export_template("osx.zip", &err)) {
- valid = true;
- }
+ // Look for export templates (first official, and if defined custom templates).
- if (p_preset->get("custom_package/debug") != "") {
- if (FileAccess::exists(p_preset->get("custom_package/debug"))) {
- valid = true;
- } else {
+ bool dvalid = exists_export_template("osx.zip", &err);
+ bool rvalid = dvalid; // Both in the same ZIP.
+
+ if (p_preset->get("custom_template/debug") != "") {
+ dvalid = FileAccess::exists(p_preset->get("custom_template/debug"));
+ if (!dvalid) {
err += TTR("Custom debug template not found.") + "\n";
}
}
-
- if (p_preset->get("custom_package/release") != "") {
- if (FileAccess::exists(p_preset->get("custom_package/release"))) {
- valid = true;
- } else {
+ if (p_preset->get("custom_template/release") != "") {
+ rvalid = FileAccess::exists(p_preset->get("custom_template/release"));
+ if (!rvalid) {
err += TTR("Custom release template not found.") + "\n";
}
}
+ valid = dvalid || rvalid;
+ r_missing_templates = !valid;
+
if (!err.empty())
r_error = err;
-
- r_missing_templates = !valid;
return valid;
}
diff --git a/platform/osx/godot_main_osx.mm b/platform/osx/godot_main_osx.mm
index 73fd4632ab..e6f8cbecf1 100644
--- a/platform/osx/godot_main_osx.mm
+++ b/platform/osx/godot_main_osx.mm
@@ -45,35 +45,6 @@ int main(int argc, char **argv) {
printf("%i: %s\n", i, argv[i]);
};
- if (argc >= 1 && argv[0][0] == '/') {
- //potentially launched from finder
- int len = strlen(argv[0]);
- while (len--) {
- if (argv[0][len] == '/') break;
- }
- if (len >= 0) {
- char *path = (char *)malloc(len + 1);
- memcpy(path, argv[0], len);
- path[len] = 0;
-
- char *pathinfo = (char *)malloc(strlen(path) + strlen("/../Info.plist") + 1);
- //in real code you would check for errors in malloc here
- strcpy(pathinfo, path);
- strcat(pathinfo, "/../Info.plist");
-
- FILE *f = fopen(pathinfo, "rb");
- if (f) {
- //running from app bundle, as Info.plist was found
- fclose(f);
- chdir(path);
- chdir("../Resources"); //data.pck, or just the files are here
- }
-
- free(path);
- free(pathinfo);
- }
- }
-
#ifdef DEBUG_ENABLED
// lets report the path we made current after all that
char cwd[4096];
diff --git a/platform/osx/os_osx.h b/platform/osx/os_osx.h
index 53b44af867..190dbcf662 100644
--- a/platform/osx/os_osx.h
+++ b/platform/osx/os_osx.h
@@ -76,8 +76,6 @@ public:
List<String> args;
MainLoop *main_loop;
- IP_Unix *ip_unix;
-
#ifdef COREAUDIO_ENABLED
AudioDriverCoreAudio audio_driver;
#endif
@@ -121,6 +119,7 @@ public:
bool maximized;
bool zoomed;
bool resizable;
+ bool window_focused;
Size2 window_size;
Rect2 restore_rect;
@@ -222,6 +221,7 @@ public:
virtual String get_config_path() const;
virtual String get_data_path() const;
virtual String get_cache_path() const;
+ virtual String get_bundle_resource_dir() const;
virtual String get_godot_dir_name() const;
virtual String get_system_dir(SystemDir p_dir) const;
@@ -274,6 +274,7 @@ public:
virtual bool is_window_maximized() const;
virtual void set_window_always_on_top(bool p_enabled);
virtual bool is_window_always_on_top() const;
+ virtual bool is_window_focused() const;
virtual void request_attention();
virtual String get_joy_guid(int p_device) const;
diff --git a/platform/osx/os_osx.mm b/platform/osx/os_osx.mm
index 7225fbf43d..6a214b8669 100644
--- a/platform/osx/os_osx.mm
+++ b/platform/osx/os_osx.mm
@@ -393,9 +393,6 @@ static Vector2 get_mouse_pos(NSPoint locationInWindow, CGFloat backingScaleFacto
}
- (void)windowDidBecomeKey:(NSNotification *)notification {
- //_GodotInputWindowFocus(window, GL_TRUE);
- //_GodotPlatformSetCursorMode(window, window->cursorMode);
-
if (OS_OSX::singleton->get_main_loop()) {
get_mouse_pos(
[OS_OSX::singleton->window_object mouseLocationOutsideOfEventStream],
@@ -404,25 +401,31 @@ static Vector2 get_mouse_pos(NSPoint locationInWindow, CGFloat backingScaleFacto
OS_OSX::singleton->get_main_loop()->notification(MainLoop::NOTIFICATION_WM_FOCUS_IN);
}
+
+ OS_OSX::singleton->window_focused = true;
}
- (void)windowDidResignKey:(NSNotification *)notification {
- //_GodotInputWindowFocus(window, GL_FALSE);
- //_GodotPlatformSetCursorMode(window, Godot_CURSOR_NORMAL);
if (OS_OSX::singleton->get_main_loop())
OS_OSX::singleton->get_main_loop()->notification(MainLoop::NOTIFICATION_WM_FOCUS_OUT);
+
+ OS_OSX::singleton->window_focused = false;
}
- (void)windowDidMiniaturize:(NSNotification *)notification {
OS_OSX::singleton->wm_minimized(true);
if (OS_OSX::singleton->get_main_loop())
OS_OSX::singleton->get_main_loop()->notification(MainLoop::NOTIFICATION_WM_FOCUS_OUT);
+
+ OS_OSX::singleton->window_focused = false;
};
- (void)windowDidDeminiaturize:(NSNotification *)notification {
OS_OSX::singleton->wm_minimized(false);
if (OS_OSX::singleton->get_main_loop())
OS_OSX::singleton->get_main_loop()->notification(MainLoop::NOTIFICATION_WM_FOCUS_IN);
+
+ OS_OSX::singleton->window_focused = true;
};
@end
@@ -476,7 +479,7 @@ static const NSRange kEmptyRange = { NSNotFound, 0 };
}
- (NSRange)markedRange {
- return (markedText.length > 0) ? NSMakeRange(0, markedText.length - 1) : kEmptyRange;
+ return NSMakeRange(0, markedText.length);
}
- (NSRange)selectedRange {
@@ -489,6 +492,10 @@ static const NSRange kEmptyRange = { NSNotFound, 0 };
} else {
[markedText initWithString:aString];
}
+ if (markedText.length == 0) {
+ [self unmarkText];
+ return;
+ }
if (OS_OSX::singleton->im_active) {
imeInputEventInProgress = true;
OS_OSX::singleton->im_text.parse_utf8([[markedText mutableString] UTF8String]);
@@ -2108,6 +2115,19 @@ String OS_OSX::get_cache_path() const {
}
}
+String OS_OSX::get_bundle_resource_dir() const {
+
+ NSBundle *main = [NSBundle mainBundle];
+ NSString *resourcePath = [main resourcePath];
+
+ char *utfs = strdup([resourcePath UTF8String]);
+ String ret;
+ ret.parse_utf8(utfs);
+ free(utfs);
+
+ return ret;
+}
+
// Get properly capitalized engine name for system paths
String OS_OSX::get_godot_dir_name() const {
@@ -2607,6 +2627,10 @@ bool OS_OSX::is_window_always_on_top() const {
return [window_object level] == NSFloatingWindowLevel;
}
+bool OS_OSX::is_window_focused() const {
+ return window_focused;
+}
+
void OS_OSX::request_attention() {
[NSApp requestUserAttention:NSCriticalRequest];
@@ -3059,6 +3083,7 @@ OS_OSX::OS_OSX() {
window_size = Vector2(1024, 600);
zoomed = false;
resizable = false;
+ window_focused = true;
Vector<Logger *> loggers;
loggers.push_back(memnew(OSXTerminalLogger));
diff --git a/platform/server/detect.py b/platform/server/detect.py
index b6028c20e3..d82df77957 100644
--- a/platform/server/detect.py
+++ b/platform/server/detect.py
@@ -162,7 +162,7 @@ def configure(env):
if not env['builtin_enet']:
env.ParseConfig('pkg-config libenet --cflags --libs')
- if not env['builtin_squish'] and env['tools']:
+ if not env['builtin_squish']:
env.ParseConfig('pkg-config libsquish --cflags --libs')
if not env['builtin_zstd']:
diff --git a/platform/server/os_server.h b/platform/server/os_server.h
index 0aca8049f2..46ca9cb6d1 100644
--- a/platform/server/os_server.h
+++ b/platform/server/os_server.h
@@ -58,7 +58,6 @@ class OS_Server : public OS_Unix {
bool grab;
virtual void delete_main_loop();
- IP_Unix *ip_unix;
bool force_quit;
diff --git a/platform/uwp/export/export.cpp b/platform/uwp/export/export.cpp
index 3fa5512819..57fb9004b8 100644
--- a/platform/uwp/export/export.cpp
+++ b/platform/uwp/export/export.cpp
@@ -1090,15 +1090,14 @@ public:
}
virtual bool can_export(const Ref<EditorExportPreset> &p_preset, String &r_error, bool &r_missing_templates) const {
+
String err;
- bool valid = true;
- Platform arch = (Platform)(int)(p_preset->get("architecture/target"));
+ bool valid = false;
- String custom_debug_binary = p_preset->get("custom_template/debug");
- String custom_release_binary = p_preset->get("custom_template/release");
+ // Look for export templates (first official, and if defined custom templates).
+ Platform arch = (Platform)(int)(p_preset->get("architecture/target"));
String platform_infix;
-
switch (arch) {
case EditorExportPlatformUWP::ARM: {
platform_infix = "arm";
@@ -1111,38 +1110,26 @@ public:
} break;
}
- if (!exists_export_template("uwp_" + platform_infix + "_debug.zip", &err) || !exists_export_template("uwp_" + platform_infix + "_release.zip", &err)) {
- valid = false;
- r_missing_templates = true;
- }
+ bool dvalid = exists_export_template("uwp_" + platform_infix + "_debug.zip", &err);
+ bool rvalid = exists_export_template("uwp_" + platform_infix + "_release.zip", &err);
- if (!valid && custom_debug_binary == "" && custom_release_binary == "") {
- if (!err.empty()) {
- r_error = err;
+ if (p_preset->get("custom_template/debug") != "") {
+ dvalid = FileAccess::exists(p_preset->get("custom_template/debug"));
+ if (!dvalid) {
+ err += TTR("Custom debug template not found.") + "\n";
}
- return valid;
}
-
- bool dvalid = true;
- bool rvalid = true;
-
- if (!FileAccess::exists(custom_debug_binary)) {
- dvalid = false;
- err += TTR("Custom debug template not found.") + "\n";
- }
-
- if (!FileAccess::exists(custom_release_binary)) {
- rvalid = false;
- err += TTR("Custom release template not found.") + "\n";
+ if (p_preset->get("custom_template/release") != "") {
+ rvalid = FileAccess::exists(p_preset->get("custom_template/release"));
+ if (!rvalid) {
+ err += TTR("Custom release template not found.") + "\n";
+ }
}
- if (dvalid || rvalid)
- valid = true;
+ valid = dvalid || rvalid;
+ r_missing_templates = !valid;
- if (!valid) {
- r_error = err;
- return valid;
- }
+ // Validate the rest of the configuration.
if (!_valid_resource_name(p_preset->get("package/short_name"))) {
valid = false;
diff --git a/platform/windows/context_gl_windows.cpp b/platform/windows/context_gl_windows.cpp
index 21d954a736..ad62e3a306 100644
--- a/platform/windows/context_gl_windows.cpp
+++ b/platform/windows/context_gl_windows.cpp
@@ -43,6 +43,11 @@
#define WGL_CONTEXT_PROFILE_MASK_ARB 0x9126
#define WGL_CONTEXT_CORE_PROFILE_BIT_ARB 0x00000001
+#if defined(__GNUC__)
+// Workaround GCC warning from -Wcast-function-type.
+#define wglGetProcAddress (void *)wglGetProcAddress
+#endif
+
typedef HGLRC(APIENTRY *PFNWGLCREATECONTEXTATTRIBSARBPROC)(HDC, HGLRC, const int *);
void ContextGL_Windows::release_current() {
@@ -89,7 +94,7 @@ void ContextGL_Windows::swap_buffers() {
if (use_vsync) {
bool vsync_via_compositor_now = should_vsync_via_compositor();
- if (vsync_via_compositor_now) {
+ if (vsync_via_compositor_now && wglGetSwapIntervalEXT() == 0) {
DwmFlush();
}
@@ -205,6 +210,7 @@ Error ContextGL_Windows::initialize() {
}
wglSwapIntervalEXT = (PFNWGLSWAPINTERVALEXTPROC)wglGetProcAddress("wglSwapIntervalEXT");
+ wglGetSwapIntervalEXT = (PFNWGLGETSWAPINTERVALEXTPROC)wglGetProcAddress("wglGetSwapIntervalEXT");
//glWrapperInit(wrapper_get_proc_address);
return OK;
diff --git a/platform/windows/context_gl_windows.h b/platform/windows/context_gl_windows.h
index 0c6a6d1814..280c5a1e3c 100644
--- a/platform/windows/context_gl_windows.h
+++ b/platform/windows/context_gl_windows.h
@@ -41,6 +41,7 @@
#include <windows.h>
typedef bool(APIENTRY *PFNWGLSWAPINTERVALEXTPROC)(int interval);
+typedef int(APIENTRY *PFNWGLGETSWAPINTERVALEXTPROC)(void);
class ContextGL_Windows {
@@ -53,6 +54,7 @@ class ContextGL_Windows {
bool vsync_via_compositor;
PFNWGLSWAPINTERVALEXTPROC wglSwapIntervalEXT;
+ PFNWGLGETSWAPINTERVALEXTPROC wglGetSwapIntervalEXT;
static bool should_vsync_via_compositor();
diff --git a/platform/windows/godot_res.rc b/platform/windows/godot_res.rc
index 1fa8957f15..0593c8b069 100644
--- a/platform/windows/godot_res.rc
+++ b/platform/windows/godot_res.rc
@@ -4,10 +4,6 @@
#define _MKSTR(m_x) _STR(m_x)
#endif
-#ifndef VERSION_PATCH
-#define VERSION_PATCH 0
-#endif
-
GODOT_ICON ICON platform/windows/godot.ico
1 VERSIONINFO
diff --git a/platform/windows/joypad_windows.cpp b/platform/windows/joypad_windows.cpp
index c82a90bf7d..49432435b9 100644
--- a/platform/windows/joypad_windows.cpp
+++ b/platform/windows/joypad_windows.cpp
@@ -37,6 +37,11 @@
#define __builtin_bswap32 _byteswap_ulong
#endif
+#if defined(__GNUC__)
+// Workaround GCC warning from -Wcast-function-type.
+#define GetProcAddress (void *)GetProcAddress
+#endif
+
DWORD WINAPI _xinput_get_state(DWORD dwUserIndex, XINPUT_STATE *pState) {
return ERROR_DEVICE_NOT_CONNECTED;
}
diff --git a/platform/windows/os_windows.cpp b/platform/windows/os_windows.cpp
index cee848f270..a6977a7a86 100755
--- a/platform/windows/os_windows.cpp
+++ b/platform/windows/os_windows.cpp
@@ -74,6 +74,11 @@ __declspec(dllexport) int AmdPowerXpressRequestHighPerformance = 1;
#define WM_POINTERUPDATE 0x0245
#endif
+#if defined(__GNUC__)
+// Workaround GCC warning from -Wcast-function-type.
+#define GetProcAddress (void *)GetProcAddress
+#endif
+
typedef struct {
int count;
int screen;
@@ -352,12 +357,14 @@ LRESULT OS_Windows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
if (LOWORD(wParam) == WA_ACTIVE || LOWORD(wParam) == WA_CLICKACTIVE) {
main_loop->notification(MainLoop::NOTIFICATION_WM_FOCUS_IN);
+ window_focused = true;
alt_mem = false;
control_mem = false;
shift_mem = false;
} else { // WM_INACTIVE
input->release_pressed_events();
main_loop->notification(MainLoop::NOTIFICATION_WM_FOCUS_OUT);
+ window_focused = false;
alt_mem = false;
};
@@ -2095,6 +2102,11 @@ bool OS_Windows::is_window_always_on_top() const {
return video_mode.always_on_top;
}
+bool OS_Windows::is_window_focused() const {
+
+ return window_focused;
+}
+
void OS_Windows::set_console_visible(bool p_enabled) {
if (console_visible == p_enabled)
return;
@@ -3372,6 +3384,7 @@ OS_Windows::OS_Windows(HINSTANCE _hInstance) {
meta_mem = false;
minimized = false;
was_maximized = false;
+ window_focused = true;
console_visible = IsWindowVisible(GetConsoleWindow());
//Note: Functions for pen input, available on Windows 8+
diff --git a/platform/windows/os_windows.h b/platform/windows/os_windows.h
index 20b61e3dbe..65d08f5d36 100644
--- a/platform/windows/os_windows.h
+++ b/platform/windows/os_windows.h
@@ -274,6 +274,7 @@ protected:
bool maximized;
bool minimized;
bool borderless;
+ bool window_focused;
bool console_visible;
bool was_maximized;
@@ -322,6 +323,7 @@ public:
virtual bool is_window_maximized() const;
virtual void set_window_always_on_top(bool p_enabled);
virtual bool is_window_always_on_top() const;
+ virtual bool is_window_focused() const;
virtual void set_console_visible(bool p_enabled);
virtual bool is_console_visible() const;
virtual void request_attention();
diff --git a/platform/x11/crash_handler_x11.cpp b/platform/x11/crash_handler_x11.cpp
index 3a91c62546..19c8f71d0e 100644
--- a/platform/x11/crash_handler_x11.cpp
+++ b/platform/x11/crash_handler_x11.cpp
@@ -107,7 +107,7 @@ static void handle_crash(int sig) {
output.erase(output.length() - 1, 1);
}
- fprintf(stderr, "[%ld] %s (%ls)\n", i, fname, output.c_str());
+ fprintf(stderr, "[%ld] %s (%ls)\n", (long int)i, fname, output.c_str());
}
free(strings);
diff --git a/platform/x11/detect.py b/platform/x11/detect.py
index b8ff97279d..957779ee83 100644
--- a/platform/x11/detect.py
+++ b/platform/x11/detect.py
@@ -171,7 +171,7 @@ def configure(env):
else:
env.Append(CCFLAGS=['-flto'])
env.Append(LINKFLAGS=['-flto'])
-
+
if not env['use_llvm']:
env['RANLIB'] = 'gcc-ranlib'
env['AR'] = 'gcc-ar'
@@ -232,7 +232,7 @@ def configure(env):
if not env['builtin_enet']:
env.ParseConfig('pkg-config libenet --cflags --libs')
- if not env['builtin_squish'] and env['tools']:
+ if not env['builtin_squish']:
env.ParseConfig('pkg-config libsquish --cflags --libs')
if not env['builtin_zstd']:
@@ -329,9 +329,15 @@ def configure(env):
if env["execinfo"]:
env.Append(LIBS=['execinfo'])
-
+
if not env['tools']:
- env.Append(LINKFLAGS=['-T', 'platform/x11/pck_embed.ld'])
+ import subprocess
+ import re
+ binutils_version = re.search('\s(\d+\.\d+)', str(subprocess.check_output(['ld', '-v']))).group(1)
+ if float(binutils_version) >= 2.30:
+ env.Append(LINKFLAGS=['-T', 'platform/x11/pck_embed.ld'])
+ else:
+ env.Append(LINKFLAGS=['-T', 'platform/x11/pck_embed.legacy.ld'])
## Cross-compilation
diff --git a/platform/x11/os_x11.cpp b/platform/x11/os_x11.cpp
index b9cfd6f386..2f0d49e6dd 100644
--- a/platform/x11/os_x11.cpp
+++ b/platform/x11/os_x11.cpp
@@ -1684,6 +1684,10 @@ bool OS_X11::is_window_always_on_top() const {
return current_videomode.always_on_top;
}
+bool OS_X11::is_window_focused() const {
+ return window_focused;
+}
+
void OS_X11::set_borderless_window(bool p_borderless) {
if (get_borderless_window() == p_borderless)
@@ -2276,6 +2280,8 @@ void OS_X11::process_xevents() {
minimized = false;
window_has_focus = true;
main_loop->notification(MainLoop::NOTIFICATION_WM_FOCUS_IN);
+ window_focused = true;
+
if (mouse_mode_grab) {
// Show and update the cursor if confined and the window regained focus.
if (mouse_mode == MOUSE_MODE_CONFINED)
@@ -2303,6 +2309,7 @@ void OS_X11::process_xevents() {
window_has_focus = false;
input->release_pressed_events();
main_loop->notification(MainLoop::NOTIFICATION_WM_FOCUS_OUT);
+ window_focused = false;
if (mouse_mode_grab) {
//dear X11, I try, I really try, but you never work, you do whathever you want.
@@ -3497,6 +3504,7 @@ OS_X11::OS_X11() {
xi.last_relative_time = 0;
layered_window = false;
minimized = false;
+ window_focused = true;
xim_style = 0L;
mouse_mode = MOUSE_MODE_VISIBLE;
}
diff --git a/platform/x11/os_x11.h b/platform/x11/os_x11.h
index 35c55aab54..01e5aac3df 100644
--- a/platform/x11/os_x11.h
+++ b/platform/x11/os_x11.h
@@ -195,6 +195,7 @@ class OS_X11 : public OS_Unix {
int video_driver_index;
bool maximized;
+ bool window_focused;
//void set_wm_border(bool p_enabled);
void set_wm_fullscreen(bool p_enabled);
void set_wm_above(bool p_enabled);
@@ -284,6 +285,7 @@ public:
virtual bool is_window_maximized() const;
virtual void set_window_always_on_top(bool p_enabled);
virtual bool is_window_always_on_top() const;
+ virtual bool is_window_focused() const;
virtual void request_attention();
virtual void set_borderless_window(bool p_borderless);
diff --git a/platform/x11/pck_embed.ld b/platform/x11/pck_embed.ld
index fe09144d88..57a1994043 100644
--- a/platform/x11/pck_embed.ld
+++ b/platform/x11/pck_embed.ld
@@ -1,9 +1,9 @@
SECTIONS
{
/* Add a zero-sized section; the exporter will patch it to enclose the data appended to the executable (embedded PCK) */
- pck 0 (NOLOAD) :
+ pck 0 (INFO) :
{
- /* Just some content to avoid the linker discarding the section */
+ /* binutils >= 2.30 allow it being zero-sized, but needs something between the braces to keep the section */
. = ALIGN(8);
}
}
diff --git a/platform/x11/pck_embed.legacy.ld b/platform/x11/pck_embed.legacy.ld
new file mode 100644
index 0000000000..a23013ba7a
--- /dev/null
+++ b/platform/x11/pck_embed.legacy.ld
@@ -0,0 +1,10 @@
+SECTIONS
+{
+ /* The exporter will patch this section to enclose the data appended to the executable (embedded PCK) */
+ pck 0 (INFO) : AT ( ADDR (.rodata) + SIZEOF (.rodata) )
+ {
+ /* binutils < 2.30 need some actual content for the linker not to discard the section */
+ BYTE(0);
+ }
+}
+INSERT AFTER .rodata;
diff --git a/scene/2d/animated_sprite.cpp b/scene/2d/animated_sprite.cpp
index 28a8c4d658..917ced5feb 100644
--- a/scene/2d/animated_sprite.cpp
+++ b/scene/2d/animated_sprite.cpp
@@ -35,6 +35,7 @@
#define NORMAL_SUFFIX "_normal"
+#ifdef TOOLS_ENABLED
Dictionary AnimatedSprite::_edit_get_state() const {
Dictionary state = Node2D::_edit_get_state();
state["offset"] = offset;
@@ -72,6 +73,7 @@ bool AnimatedSprite::_edit_use_rect() const {
t = frames->get_frame(animation, frame);
return t.is_valid();
}
+#endif
Rect2 AnimatedSprite::get_anchorable_rect() const {
return _get_rect();
diff --git a/scene/2d/animated_sprite.h b/scene/2d/animated_sprite.h
index 2017c62a48..cd00a4e181 100644
--- a/scene/2d/animated_sprite.h
+++ b/scene/2d/animated_sprite.h
@@ -156,6 +156,7 @@ protected:
virtual void _validate_property(PropertyInfo &property) const;
public:
+#ifdef TOOLS_ENABLED
virtual Dictionary _edit_get_state() const;
virtual void _edit_set_state(const Dictionary &p_state);
@@ -164,6 +165,7 @@ public:
virtual bool _edit_use_pivot() const;
virtual Rect2 _edit_get_rect() const;
virtual bool _edit_use_rect() const;
+#endif
virtual Rect2 get_anchorable_rect() const;
diff --git a/scene/2d/back_buffer_copy.cpp b/scene/2d/back_buffer_copy.cpp
index 1a6f30e0fd..faeb6b7169 100644
--- a/scene/2d/back_buffer_copy.cpp
+++ b/scene/2d/back_buffer_copy.cpp
@@ -50,6 +50,7 @@ void BackBufferCopy::_update_copy_mode() {
}
}
+#ifdef TOOLS_ENABLED
Rect2 BackBufferCopy::_edit_get_rect() const {
return rect;
@@ -58,6 +59,7 @@ Rect2 BackBufferCopy::_edit_get_rect() const {
bool BackBufferCopy::_edit_use_rect() const {
return true;
}
+#endif
Rect2 BackBufferCopy::get_anchorable_rect() const {
diff --git a/scene/2d/back_buffer_copy.h b/scene/2d/back_buffer_copy.h
index 91acd81e00..4b26bf1bdc 100644
--- a/scene/2d/back_buffer_copy.h
+++ b/scene/2d/back_buffer_copy.h
@@ -53,8 +53,10 @@ protected:
static void _bind_methods();
public:
+#ifdef TOOLS_ENABLED
Rect2 _edit_get_rect() const;
virtual bool _edit_use_rect() const;
+#endif
void set_rect(const Rect2 &p_rect);
Rect2 get_rect() const;
diff --git a/scene/2d/canvas_item.cpp b/scene/2d/canvas_item.cpp
index 9895dba027..5631aa3355 100644
--- a/scene/2d/canvas_item.cpp
+++ b/scene/2d/canvas_item.cpp
@@ -351,7 +351,7 @@ CanvasItemMaterial::~CanvasItemMaterial() {
}
///////////////////////////////////////////////////////////////////
-
+#ifdef TOOLS_ENABLED
bool CanvasItem::_edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const {
if (_edit_use_rect()) {
return _edit_get_rect().has_point(p_point);
@@ -363,6 +363,7 @@ bool CanvasItem::_edit_is_selected_on_click(const Point2 &p_point, double p_tole
Transform2D CanvasItem::_edit_get_transform() const {
return Transform2D(_edit_get_rotation(), _edit_get_position() + _edit_get_pivot());
}
+#endif
bool CanvasItem::is_visible_in_tree() const {
@@ -1121,9 +1122,10 @@ void CanvasItem::_bind_methods() {
ClassDB::bind_method(D_METHOD("_toplevel_raise_self"), &CanvasItem::_toplevel_raise_self);
ClassDB::bind_method(D_METHOD("_update_callback"), &CanvasItem::_update_callback);
+
+#ifdef TOOLS_ENABLED
ClassDB::bind_method(D_METHOD("_edit_set_state", "state"), &CanvasItem::_edit_set_state);
ClassDB::bind_method(D_METHOD("_edit_get_state"), &CanvasItem::_edit_get_state);
-
ClassDB::bind_method(D_METHOD("_edit_set_position", "position"), &CanvasItem::_edit_set_position);
ClassDB::bind_method(D_METHOD("_edit_get_position"), &CanvasItem::_edit_get_position);
ClassDB::bind_method(D_METHOD("_edit_set_scale", "scale"), &CanvasItem::_edit_set_scale);
@@ -1138,6 +1140,7 @@ void CanvasItem::_bind_methods() {
ClassDB::bind_method(D_METHOD("_edit_get_pivot"), &CanvasItem::_edit_get_pivot);
ClassDB::bind_method(D_METHOD("_edit_use_pivot"), &CanvasItem::_edit_use_pivot);
ClassDB::bind_method(D_METHOD("_edit_get_transform"), &CanvasItem::_edit_get_transform);
+#endif
ClassDB::bind_method(D_METHOD("get_canvas_item"), &CanvasItem::get_canvas_item);
diff --git a/scene/2d/canvas_item.h b/scene/2d/canvas_item.h
index 82645051e8..8814d99edd 100644
--- a/scene/2d/canvas_item.h
+++ b/scene/2d/canvas_item.h
@@ -249,7 +249,7 @@ public:
};
/* EDITOR */
-
+#ifdef TOOLS_ENABLED
// Select the node
virtual bool _edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const;
@@ -282,6 +282,7 @@ public:
virtual Point2 _edit_get_pivot() const { return Point2(); };
virtual Transform2D _edit_get_transform() const;
+#endif
/* VISIBILITY */
diff --git a/scene/2d/collision_polygon_2d.cpp b/scene/2d/collision_polygon_2d.cpp
index 3090c9956e..d9cc94c6eb 100644
--- a/scene/2d/collision_polygon_2d.cpp
+++ b/scene/2d/collision_polygon_2d.cpp
@@ -227,6 +227,7 @@ CollisionPolygon2D::BuildMode CollisionPolygon2D::get_build_mode() const {
return build_mode;
}
+#ifdef TOOLS_ENABLED
Rect2 CollisionPolygon2D::_edit_get_rect() const {
return aabb;
@@ -240,6 +241,7 @@ bool CollisionPolygon2D::_edit_is_selected_on_click(const Point2 &p_point, doubl
return Geometry::is_point_in_polygon(p_point, Variant(polygon));
}
+#endif
String CollisionPolygon2D::get_configuration_warning() const {
diff --git a/scene/2d/collision_polygon_2d.h b/scene/2d/collision_polygon_2d.h
index e5e18b2674..d8dfec8fd2 100644
--- a/scene/2d/collision_polygon_2d.h
+++ b/scene/2d/collision_polygon_2d.h
@@ -67,16 +67,18 @@ protected:
static void _bind_methods();
public:
+#ifdef TOOLS_ENABLED
+ virtual Rect2 _edit_get_rect() const;
+ virtual bool _edit_use_rect() const;
+ virtual bool _edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const;
+#endif
+
void set_build_mode(BuildMode p_mode);
BuildMode get_build_mode() const;
void set_polygon(const Vector<Point2> &p_polygon);
Vector<Point2> get_polygon() const;
- virtual Rect2 _edit_get_rect() const;
- virtual bool _edit_use_rect() const;
- virtual bool _edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const;
-
virtual String get_configuration_warning() const;
void set_disabled(bool p_disabled);
diff --git a/scene/2d/cpu_particles_2d.cpp b/scene/2d/cpu_particles_2d.cpp
index 8296f35739..c325de00b8 100644
--- a/scene/2d/cpu_particles_2d.cpp
+++ b/scene/2d/cpu_particles_2d.cpp
@@ -422,7 +422,7 @@ bool CPUParticles2D::get_particle_flag(Flags p_flag) const {
}
void CPUParticles2D::set_emission_shape(EmissionShape p_shape) {
-
+ ERR_FAIL_INDEX(p_shape, EMISSION_SHAPE_MAX);
emission_shape = p_shape;
_change_notify();
}
@@ -772,6 +772,9 @@ void CPUParticles2D::_particles_process(float p_delta) {
p.base_color = emission_colors.get(random_idx);
}
} break;
+ case EMISSION_SHAPE_MAX: { // Max value for validity check.
+ break;
+ }
}
if (!local_coords) {
@@ -1416,6 +1419,7 @@ void CPUParticles2D::_bind_methods() {
BIND_ENUM_CONSTANT(EMISSION_SHAPE_RECTANGLE);
BIND_ENUM_CONSTANT(EMISSION_SHAPE_POINTS);
BIND_ENUM_CONSTANT(EMISSION_SHAPE_DIRECTED_POINTS);
+ BIND_ENUM_CONSTANT(EMISSION_SHAPE_MAX);
}
CPUParticles2D::CPUParticles2D() {
diff --git a/scene/2d/cpu_particles_2d.h b/scene/2d/cpu_particles_2d.h
index 6ffa1f0e97..cbaff70c2a 100644
--- a/scene/2d/cpu_particles_2d.h
+++ b/scene/2d/cpu_particles_2d.h
@@ -75,6 +75,7 @@ public:
EMISSION_SHAPE_RECTANGLE,
EMISSION_SHAPE_POINTS,
EMISSION_SHAPE_DIRECTED_POINTS,
+ EMISSION_SHAPE_MAX
};
private:
diff --git a/scene/2d/light_2d.cpp b/scene/2d/light_2d.cpp
index 1843cbed67..1bffaf8084 100644
--- a/scene/2d/light_2d.cpp
+++ b/scene/2d/light_2d.cpp
@@ -33,6 +33,7 @@
#include "core/engine.h"
#include "servers/visual_server.h"
+#ifdef TOOLS_ENABLED
Dictionary Light2D::_edit_get_state() const {
Dictionary state = Node2D::_edit_get_state();
state["offset"] = get_texture_offset();
@@ -68,6 +69,7 @@ Rect2 Light2D::_edit_get_rect() const {
bool Light2D::_edit_use_rect() const {
return !texture.is_null();
}
+#endif
Rect2 Light2D::get_anchorable_rect() const {
if (texture.is_null())
@@ -187,6 +189,10 @@ float Light2D::get_energy() const {
void Light2D::set_texture_scale(float p_scale) {
_scale = p_scale;
+ // Avoid having 0 scale values, can lead to errors in physics and rendering.
+ if (_scale == 0) {
+ _scale = CMP_EPSILON;
+ }
VS::get_singleton()->canvas_light_set_scale(canvas_light, _scale);
item_rect_changed();
}
diff --git a/scene/2d/light_2d.h b/scene/2d/light_2d.h
index f8476e8389..65db5c6ee6 100644
--- a/scene/2d/light_2d.h
+++ b/scene/2d/light_2d.h
@@ -85,6 +85,7 @@ protected:
static void _bind_methods();
public:
+#ifdef TOOLS_ENABLED
virtual Dictionary _edit_get_state() const;
virtual void _edit_set_state(const Dictionary &p_state);
@@ -93,6 +94,7 @@ public:
virtual bool _edit_use_pivot() const;
virtual Rect2 _edit_get_rect() const;
virtual bool _edit_use_rect() const;
+#endif
virtual Rect2 get_anchorable_rect() const;
diff --git a/scene/2d/light_occluder_2d.cpp b/scene/2d/light_occluder_2d.cpp
index 6a930683d1..0e8e8f6679 100644
--- a/scene/2d/light_occluder_2d.cpp
+++ b/scene/2d/light_occluder_2d.cpp
@@ -33,6 +33,8 @@
#include "core/engine.h"
#define LINE_GRAB_WIDTH 8
+
+#ifdef TOOLS_ENABLED
Rect2 OccluderPolygon2D::_edit_get_rect() const {
if (rect_cache_dirty) {
@@ -80,6 +82,7 @@ bool OccluderPolygon2D::_edit_is_selected_on_click(const Point2 &p_point, double
return false;
}
}
+#endif
void OccluderPolygon2D::set_polygon(const PoolVector<Vector2> &p_polygon) {
@@ -215,6 +218,7 @@ void LightOccluder2D::_notification(int p_what) {
}
}
+#ifdef TOOLS_ENABLED
Rect2 LightOccluder2D::_edit_get_rect() const {
return occluder_polygon.is_valid() ? occluder_polygon->_edit_get_rect() : Rect2();
@@ -224,6 +228,7 @@ bool LightOccluder2D::_edit_is_selected_on_click(const Point2 &p_point, double p
return occluder_polygon.is_valid() ? occluder_polygon->_edit_is_selected_on_click(p_point, p_tolerance) : false;
}
+#endif
void LightOccluder2D::set_occluder_polygon(const Ref<OccluderPolygon2D> &p_polygon) {
diff --git a/scene/2d/light_occluder_2d.h b/scene/2d/light_occluder_2d.h
index 32d527093d..b20e347c35 100644
--- a/scene/2d/light_occluder_2d.h
+++ b/scene/2d/light_occluder_2d.h
@@ -57,8 +57,10 @@ protected:
static void _bind_methods();
public:
+#ifdef TOOLS_ENABLED
virtual Rect2 _edit_get_rect() const;
virtual bool _edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const;
+#endif
void set_polygon(const PoolVector<Vector2> &p_polygon);
PoolVector<Vector2> get_polygon() const;
@@ -91,8 +93,10 @@ protected:
static void _bind_methods();
public:
+#ifdef TOOLS_ENABLED
virtual Rect2 _edit_get_rect() const;
virtual bool _edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const;
+#endif
void set_occluder_polygon(const Ref<OccluderPolygon2D> &p_polygon);
Ref<OccluderPolygon2D> get_occluder_polygon() const;
diff --git a/scene/2d/line_2d.cpp b/scene/2d/line_2d.cpp
index 4a022f0a9c..c31840c8e1 100644
--- a/scene/2d/line_2d.cpp
+++ b/scene/2d/line_2d.cpp
@@ -50,6 +50,7 @@ Line2D::Line2D() {
_antialiased = false;
}
+#ifdef TOOLS_ENABLED
Rect2 Line2D::_edit_get_rect() const {
if (_points.size() == 0)
@@ -79,6 +80,7 @@ bool Line2D::_edit_is_selected_on_click(const Point2 &p_point, double p_toleranc
return false;
}
+#endif
void Line2D::set_points(const PoolVector<Vector2> &p_points) {
_points = p_points;
diff --git a/scene/2d/line_2d.h b/scene/2d/line_2d.h
index bc2deba8c6..3c7239f67c 100644
--- a/scene/2d/line_2d.h
+++ b/scene/2d/line_2d.h
@@ -56,11 +56,13 @@ public:
LINE_TEXTURE_STRETCH
};
- Line2D();
-
+#ifdef TOOLS_ENABLED
virtual Rect2 _edit_get_rect() const;
virtual bool _edit_use_rect() const;
virtual bool _edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const;
+#endif
+
+ Line2D();
void set_points(const PoolVector<Vector2> &p_points);
PoolVector<Vector2> get_points() const;
diff --git a/scene/2d/mesh_instance_2d.cpp b/scene/2d/mesh_instance_2d.cpp
index 8f9c4e2a4d..93432ec40b 100644
--- a/scene/2d/mesh_instance_2d.cpp
+++ b/scene/2d/mesh_instance_2d.cpp
@@ -94,6 +94,7 @@ Ref<Texture> MeshInstance2D::get_texture() const {
return texture;
}
+#ifdef TOOLS_ENABLED
Rect2 MeshInstance2D::_edit_get_rect() const {
if (mesh.is_valid()) {
@@ -103,6 +104,7 @@ Rect2 MeshInstance2D::_edit_get_rect() const {
return Node2D::_edit_get_rect();
}
+#endif
MeshInstance2D::MeshInstance2D() {
}
diff --git a/scene/2d/mesh_instance_2d.h b/scene/2d/mesh_instance_2d.h
index e7f8b7c0c3..51f75a3ead 100644
--- a/scene/2d/mesh_instance_2d.h
+++ b/scene/2d/mesh_instance_2d.h
@@ -46,6 +46,10 @@ protected:
static void _bind_methods();
public:
+#ifdef TOOLS_ENABLED
+ virtual Rect2 _edit_get_rect() const;
+#endif
+
void set_mesh(const Ref<Mesh> &p_mesh);
Ref<Mesh> get_mesh() const;
@@ -55,8 +59,6 @@ public:
void set_normal_map(const Ref<Texture> &p_texture);
Ref<Texture> get_normal_map() const;
- virtual Rect2 _edit_get_rect() const;
-
MeshInstance2D();
};
diff --git a/scene/2d/multimesh_instance_2d.cpp b/scene/2d/multimesh_instance_2d.cpp
index 69d687229b..028459e778 100644
--- a/scene/2d/multimesh_instance_2d.cpp
+++ b/scene/2d/multimesh_instance_2d.cpp
@@ -94,6 +94,7 @@ Ref<Texture> MultiMeshInstance2D::get_normal_map() const {
return normal_map;
}
+#ifdef TOOLS_ENABLED
Rect2 MultiMeshInstance2D::_edit_get_rect() const {
if (multimesh.is_valid()) {
@@ -103,6 +104,7 @@ Rect2 MultiMeshInstance2D::_edit_get_rect() const {
return Node2D::_edit_get_rect();
}
+#endif
MultiMeshInstance2D::MultiMeshInstance2D() {
}
diff --git a/scene/2d/multimesh_instance_2d.h b/scene/2d/multimesh_instance_2d.h
index 253f4c77ca..c3f3e52920 100644
--- a/scene/2d/multimesh_instance_2d.h
+++ b/scene/2d/multimesh_instance_2d.h
@@ -47,6 +47,10 @@ protected:
static void _bind_methods();
public:
+#ifdef TOOLS_ENABLED
+ virtual Rect2 _edit_get_rect() const;
+#endif
+
void set_multimesh(const Ref<MultiMesh> &p_multimesh);
Ref<MultiMesh> get_multimesh() const;
@@ -56,8 +60,6 @@ public:
void set_normal_map(const Ref<Texture> &p_texture);
Ref<Texture> get_normal_map() const;
- virtual Rect2 _edit_get_rect() const;
-
MultiMeshInstance2D();
~MultiMeshInstance2D();
};
diff --git a/scene/2d/navigation_polygon.cpp b/scene/2d/navigation_polygon.cpp
index bd930bdda5..ea79f89dd9 100644
--- a/scene/2d/navigation_polygon.cpp
+++ b/scene/2d/navigation_polygon.cpp
@@ -36,6 +36,7 @@
#include "thirdparty/misc/triangulator.h"
+#ifdef TOOLS_ENABLED
Rect2 NavigationPolygon::_edit_get_rect() const {
if (rect_cache_dirty) {
@@ -75,6 +76,7 @@ bool NavigationPolygon::_edit_is_selected_on_click(const Point2 &p_point, double
}
return false;
}
+#endif
void NavigationPolygon::set_vertices(const PoolVector<Vector2> &p_vertices) {
@@ -357,7 +359,7 @@ bool NavigationPolygonInstance::is_enabled() const {
}
/////////////////////////////
-
+#ifdef TOOLS_ENABLED
Rect2 NavigationPolygonInstance::_edit_get_rect() const {
return navpoly.is_valid() ? navpoly->_edit_get_rect() : Rect2();
@@ -367,6 +369,7 @@ bool NavigationPolygonInstance::_edit_is_selected_on_click(const Point2 &p_point
return navpoly.is_valid() ? navpoly->_edit_is_selected_on_click(p_point, p_tolerance) : false;
}
+#endif
void NavigationPolygonInstance::_notification(int p_what) {
diff --git a/scene/2d/navigation_polygon.h b/scene/2d/navigation_polygon.h
index 9bbaa864f4..cbc1711a32 100644
--- a/scene/2d/navigation_polygon.h
+++ b/scene/2d/navigation_polygon.h
@@ -57,8 +57,10 @@ protected:
Array _get_outlines() const;
public:
+#ifdef TOOLS_ENABLED
Rect2 _edit_get_rect() const;
bool _edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const;
+#endif
void set_vertices(const PoolVector<Vector2> &p_vertices);
PoolVector<Vector2> get_vertices() const;
@@ -100,8 +102,10 @@ protected:
static void _bind_methods();
public:
+#ifdef TOOLS_ENABLED
virtual Rect2 _edit_get_rect() const;
virtual bool _edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const;
+#endif
void set_enabled(bool p_enabled);
bool is_enabled() const;
diff --git a/scene/2d/node_2d.cpp b/scene/2d/node_2d.cpp
index ad04dc8d9e..7deebe9b27 100644
--- a/scene/2d/node_2d.cpp
+++ b/scene/2d/node_2d.cpp
@@ -35,6 +35,7 @@
#include "scene/main/viewport.h"
#include "servers/visual_server.h"
+#ifdef TOOLS_ENABLED
Dictionary Node2D::_edit_get_state() const {
Dictionary state;
@@ -44,6 +45,7 @@ Dictionary Node2D::_edit_get_state() const {
return state;
}
+
void Node2D::_edit_set_state(const Dictionary &p_state) {
pos = p_state["position"];
@@ -119,6 +121,7 @@ void Node2D::_edit_set_rect(const Rect2 &p_edit_rect) {
_change_notify("scale");
_change_notify("position");
}
+#endif
void Node2D::_update_xform_values() {
@@ -170,6 +173,7 @@ void Node2D::set_scale(const Size2 &p_scale) {
if (_xform_dirty)
((Node2D *)this)->_update_xform_values();
_scale = p_scale;
+ // Avoid having 0 scale values, can lead to errors in physics and rendering.
if (_scale.x == 0)
_scale.x = CMP_EPSILON;
if (_scale.y == 0)
diff --git a/scene/2d/node_2d.h b/scene/2d/node_2d.h
index a03ccc5a80..00202481a6 100644
--- a/scene/2d/node_2d.h
+++ b/scene/2d/node_2d.h
@@ -55,6 +55,7 @@ protected:
static void _bind_methods();
public:
+#ifdef TOOLS_ENABLED
virtual Dictionary _edit_get_state() const;
virtual void _edit_set_state(const Dictionary &p_state);
@@ -69,6 +70,7 @@ public:
virtual bool _edit_use_rotation() const;
virtual void _edit_set_rect(const Rect2 &p_edit_rect);
+#endif
void set_position(const Point2 &p_pos);
void set_rotation(float p_radians);
diff --git a/scene/2d/path_2d.cpp b/scene/2d/path_2d.cpp
index e6ae95af89..e9296b0fe7 100644
--- a/scene/2d/path_2d.cpp
+++ b/scene/2d/path_2d.cpp
@@ -37,6 +37,7 @@
#include "editor/editor_scale.h"
#endif
+#ifdef TOOLS_ENABLED
Rect2 Path2D::_edit_get_rect() const {
if (!curve.is_valid() || curve->get_point_count() == 0)
@@ -85,6 +86,7 @@ bool Path2D::_edit_is_selected_on_click(const Point2 &p_point, double p_toleranc
return false;
}
+#endif
void Path2D::_notification(int p_what) {
diff --git a/scene/2d/path_2d.h b/scene/2d/path_2d.h
index 21cb4374bd..35cf8211f4 100644
--- a/scene/2d/path_2d.h
+++ b/scene/2d/path_2d.h
@@ -47,9 +47,11 @@ protected:
static void _bind_methods();
public:
+#ifdef TOOLS_ENABLED
virtual Rect2 _edit_get_rect() const;
virtual bool _edit_use_rect() const;
virtual bool _edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const;
+#endif
void set_curve(const Ref<Curve2D> &p_curve);
Ref<Curve2D> get_curve() const;
diff --git a/scene/2d/physics_body_2d.cpp b/scene/2d/physics_body_2d.cpp
index 3fd0bef7e9..d42bd6adaf 100644
--- a/scene/2d/physics_body_2d.cpp
+++ b/scene/2d/physics_body_2d.cpp
@@ -1212,7 +1212,7 @@ bool KinematicBody2D::move_and_collide(const Vector2 &p_motion, bool p_infinite_
//so, if you pass 45 as limit, avoid numerical precision errors when angle is 45.
#define FLOOR_ANGLE_THRESHOLD 0.01
-Vector2 KinematicBody2D::move_and_slide(const Vector2 &p_linear_velocity, const Vector2 &p_floor_direction, bool p_stop_on_slope, int p_max_slides, float p_floor_max_angle, bool p_infinite_inertia) {
+Vector2 KinematicBody2D::move_and_slide(const Vector2 &p_linear_velocity, const Vector2 &p_up_direction, bool p_stop_on_slope, int p_max_slides, float p_floor_max_angle, bool p_infinite_inertia) {
Vector2 body_velocity = p_linear_velocity;
Vector2 body_velocity_normal = body_velocity.normalized();
@@ -1234,6 +1234,7 @@ Vector2 KinematicBody2D::move_and_slide(const Vector2 &p_linear_velocity, const
on_ceiling = false;
on_wall = false;
colliders.clear();
+ floor_normal = Vector2();
floor_velocity = Vector2();
while (p_max_slides) {
@@ -1262,25 +1263,26 @@ Vector2 KinematicBody2D::move_and_slide(const Vector2 &p_linear_velocity, const
colliders.push_back(collision);
motion = collision.remainder;
- if (p_floor_direction == Vector2()) {
+ if (p_up_direction == Vector2()) {
//all is a wall
on_wall = true;
} else {
- if (Math::acos(collision.normal.dot(p_floor_direction)) <= p_floor_max_angle + FLOOR_ANGLE_THRESHOLD) { //floor
+ if (Math::acos(collision.normal.dot(p_up_direction)) <= p_floor_max_angle + FLOOR_ANGLE_THRESHOLD) { //floor
on_floor = true;
+ floor_normal = collision.normal;
on_floor_body = collision.collider_rid;
floor_velocity = collision.collider_vel;
if (p_stop_on_slope) {
- if ((body_velocity_normal + p_floor_direction).length() < 0.01 && collision.travel.length() < 1) {
+ if ((body_velocity_normal + p_up_direction).length() < 0.01 && collision.travel.length() < 1) {
Transform2D gt = get_global_transform();
- gt.elements[2] -= collision.travel.slide(p_floor_direction);
+ gt.elements[2] -= collision.travel.slide(p_up_direction);
set_global_transform(gt);
return Vector2();
}
}
- } else if (Math::acos(collision.normal.dot(-p_floor_direction)) <= p_floor_max_angle + FLOOR_ANGLE_THRESHOLD) { //ceiling
+ } else if (Math::acos(collision.normal.dot(-p_up_direction)) <= p_floor_max_angle + FLOOR_ANGLE_THRESHOLD) { //ceiling
on_ceiling = true;
} else {
on_wall = true;
@@ -1301,11 +1303,11 @@ Vector2 KinematicBody2D::move_and_slide(const Vector2 &p_linear_velocity, const
return body_velocity;
}
-Vector2 KinematicBody2D::move_and_slide_with_snap(const Vector2 &p_linear_velocity, const Vector2 &p_snap, const Vector2 &p_floor_direction, bool p_stop_on_slope, int p_max_slides, float p_floor_max_angle, bool p_infinite_inertia) {
+Vector2 KinematicBody2D::move_and_slide_with_snap(const Vector2 &p_linear_velocity, const Vector2 &p_snap, const Vector2 &p_up_direction, bool p_stop_on_slope, int p_max_slides, float p_floor_max_angle, bool p_infinite_inertia) {
bool was_on_floor = on_floor;
- Vector2 ret = move_and_slide(p_linear_velocity, p_floor_direction, p_stop_on_slope, p_max_slides, p_floor_max_angle, p_infinite_inertia);
+ Vector2 ret = move_and_slide(p_linear_velocity, p_up_direction, p_stop_on_slope, p_max_slides, p_floor_max_angle, p_infinite_inertia);
if (!was_on_floor || p_snap == Vector2()) {
return ret;
}
@@ -1315,15 +1317,16 @@ Vector2 KinematicBody2D::move_and_slide_with_snap(const Vector2 &p_linear_veloci
if (move_and_collide(p_snap, p_infinite_inertia, col, false, true)) {
bool apply = true;
- if (p_floor_direction != Vector2()) {
- if (Math::acos(p_floor_direction.normalized().dot(col.normal)) < p_floor_max_angle) {
+ if (p_up_direction != Vector2()) {
+ if (Math::acos(p_up_direction.normalized().dot(col.normal)) < p_floor_max_angle) {
on_floor = true;
+ floor_normal = col.normal;
on_floor_body = col.collider_rid;
floor_velocity = col.collider_vel;
if (p_stop_on_slope) {
// move and collide may stray the object a bit because of pre un-stucking,
// so only ensure that motion happens on floor direction in this case.
- col.travel = p_floor_direction * p_floor_direction.dot(col.travel);
+ col.travel = p_up_direction * p_up_direction.dot(col.travel);
}
} else {
@@ -1353,6 +1356,11 @@ bool KinematicBody2D::is_on_ceiling() const {
return on_ceiling;
}
+Vector2 KinematicBody2D::get_floor_normal() const {
+
+ return floor_normal;
+}
+
Vector2 KinematicBody2D::get_floor_velocity() const {
return floor_velocity;
@@ -1465,14 +1473,15 @@ void KinematicBody2D::_notification(int p_what) {
void KinematicBody2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("move_and_collide", "rel_vec", "infinite_inertia", "exclude_raycast_shapes", "test_only"), &KinematicBody2D::_move, DEFVAL(true), DEFVAL(true), DEFVAL(false));
- ClassDB::bind_method(D_METHOD("move_and_slide", "linear_velocity", "floor_normal", "stop_on_slope", "max_slides", "floor_max_angle", "infinite_inertia"), &KinematicBody2D::move_and_slide, DEFVAL(Vector2(0, 0)), DEFVAL(false), DEFVAL(4), DEFVAL(Math::deg2rad((float)45)), DEFVAL(true));
- ClassDB::bind_method(D_METHOD("move_and_slide_with_snap", "linear_velocity", "snap", "floor_normal", "stop_on_slope", "max_slides", "floor_max_angle", "infinite_inertia"), &KinematicBody2D::move_and_slide_with_snap, DEFVAL(Vector2(0, 0)), DEFVAL(false), DEFVAL(4), DEFVAL(Math::deg2rad((float)45)), DEFVAL(true));
+ ClassDB::bind_method(D_METHOD("move_and_slide", "linear_velocity", "up_direction", "stop_on_slope", "max_slides", "floor_max_angle", "infinite_inertia"), &KinematicBody2D::move_and_slide, DEFVAL(Vector2(0, 0)), DEFVAL(false), DEFVAL(4), DEFVAL(Math::deg2rad((float)45)), DEFVAL(true));
+ ClassDB::bind_method(D_METHOD("move_and_slide_with_snap", "linear_velocity", "snap", "up_direction", "stop_on_slope", "max_slides", "floor_max_angle", "infinite_inertia"), &KinematicBody2D::move_and_slide_with_snap, DEFVAL(Vector2(0, 0)), DEFVAL(false), DEFVAL(4), DEFVAL(Math::deg2rad((float)45)), DEFVAL(true));
ClassDB::bind_method(D_METHOD("test_move", "from", "rel_vec", "infinite_inertia"), &KinematicBody2D::test_move, DEFVAL(true));
ClassDB::bind_method(D_METHOD("is_on_floor"), &KinematicBody2D::is_on_floor);
ClassDB::bind_method(D_METHOD("is_on_ceiling"), &KinematicBody2D::is_on_ceiling);
ClassDB::bind_method(D_METHOD("is_on_wall"), &KinematicBody2D::is_on_wall);
+ ClassDB::bind_method(D_METHOD("get_floor_normal"), &KinematicBody2D::get_floor_normal);
ClassDB::bind_method(D_METHOD("get_floor_velocity"), &KinematicBody2D::get_floor_velocity);
ClassDB::bind_method(D_METHOD("set_safe_margin", "pixels"), &KinematicBody2D::set_safe_margin);
diff --git a/scene/2d/physics_body_2d.h b/scene/2d/physics_body_2d.h
index 7f2b42b554..6766bafde3 100644
--- a/scene/2d/physics_body_2d.h
+++ b/scene/2d/physics_body_2d.h
@@ -306,6 +306,7 @@ public:
private:
float margin;
+ Vector2 floor_normal;
Vector2 floor_velocity;
RID on_floor_body;
bool on_floor;
@@ -339,11 +340,12 @@ public:
void set_safe_margin(float p_margin);
float get_safe_margin() const;
- Vector2 move_and_slide(const Vector2 &p_linear_velocity, const Vector2 &p_floor_direction = Vector2(0, 0), bool p_stop_on_slope = false, int p_max_slides = 4, float p_floor_max_angle = Math::deg2rad((float)45), bool p_infinite_inertia = true);
- Vector2 move_and_slide_with_snap(const Vector2 &p_linear_velocity, const Vector2 &p_snap, const Vector2 &p_floor_direction = Vector2(0, 0), bool p_stop_on_slope = false, int p_max_slides = 4, float p_floor_max_angle = Math::deg2rad((float)45), bool p_infinite_inertia = true);
+ Vector2 move_and_slide(const Vector2 &p_linear_velocity, const Vector2 &p_up_direction = Vector2(0, 0), bool p_stop_on_slope = false, int p_max_slides = 4, float p_floor_max_angle = Math::deg2rad((float)45), bool p_infinite_inertia = true);
+ Vector2 move_and_slide_with_snap(const Vector2 &p_linear_velocity, const Vector2 &p_snap, const Vector2 &p_up_direction = Vector2(0, 0), bool p_stop_on_slope = false, int p_max_slides = 4, float p_floor_max_angle = Math::deg2rad((float)45), bool p_infinite_inertia = true);
bool is_on_floor() const;
bool is_on_wall() const;
bool is_on_ceiling() const;
+ Vector2 get_floor_normal() const;
Vector2 get_floor_velocity() const;
int get_slide_count() const;
diff --git a/scene/2d/polygon_2d.cpp b/scene/2d/polygon_2d.cpp
index 7b03193fe0..c480423eca 100644
--- a/scene/2d/polygon_2d.cpp
+++ b/scene/2d/polygon_2d.cpp
@@ -33,6 +33,7 @@
#include "core/math/geometry.h"
#include "skeleton_2d.h"
+#ifdef TOOLS_ENABLED
Dictionary Polygon2D::_edit_get_state() const {
Dictionary state = Node2D::_edit_get_state();
state["offset"] = offset;
@@ -87,6 +88,7 @@ bool Polygon2D::_edit_is_selected_on_click(const Point2 &p_point, double p_toler
}
return Geometry::is_point_in_polygon(p_point - get_offset(), polygon2d);
}
+#endif
void Polygon2D::_skeleton_bone_setup_changed() {
update();
diff --git a/scene/2d/polygon_2d.h b/scene/2d/polygon_2d.h
index 84ad221760..07b8828532 100644
--- a/scene/2d/polygon_2d.h
+++ b/scene/2d/polygon_2d.h
@@ -77,6 +77,7 @@ protected:
static void _bind_methods();
public:
+#ifdef TOOLS_ENABLED
virtual Dictionary _edit_get_state() const;
virtual void _edit_set_state(const Dictionary &p_state);
@@ -87,6 +88,7 @@ public:
virtual bool _edit_use_rect() const;
virtual bool _edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const;
+#endif
void set_polygon(const PoolVector<Vector2> &p_polygon);
PoolVector<Vector2> get_polygon() const;
diff --git a/scene/2d/position_2d.cpp b/scene/2d/position_2d.cpp
index 49ef92b861..cdeb905c0c 100644
--- a/scene/2d/position_2d.cpp
+++ b/scene/2d/position_2d.cpp
@@ -43,6 +43,7 @@ void Position2D::_draw_cross() {
draw_line(Point2(0, -extents), Point2(0, +extents), Color(0.53, 0.84, 0.01));
}
+#ifdef TOOLS_ENABLED
Rect2 Position2D::_edit_get_rect() const {
float extents = get_gizmo_extents();
@@ -52,6 +53,7 @@ Rect2 Position2D::_edit_get_rect() const {
bool Position2D::_edit_use_rect() const {
return false;
}
+#endif
void Position2D::_notification(int p_what) {
diff --git a/scene/2d/position_2d.h b/scene/2d/position_2d.h
index 711c4ec02f..3ea636171d 100644
--- a/scene/2d/position_2d.h
+++ b/scene/2d/position_2d.h
@@ -44,8 +44,10 @@ protected:
static void _bind_methods();
public:
+#ifdef TOOLS_ENABLED
virtual Rect2 _edit_get_rect() const;
virtual bool _edit_use_rect() const;
+#endif
void set_gizmo_extents(float p_extents);
float get_gizmo_extents() const;
diff --git a/scene/2d/sprite.cpp b/scene/2d/sprite.cpp
index 837444532c..55daed0585 100644
--- a/scene/2d/sprite.cpp
+++ b/scene/2d/sprite.cpp
@@ -34,6 +34,7 @@
#include "scene/main/viewport.h"
#include "scene/scene_string_names.h"
+#ifdef TOOLS_ENABLED
Dictionary Sprite::_edit_get_state() const {
Dictionary state = Node2D::_edit_get_state();
state["offset"] = offset;
@@ -58,6 +59,11 @@ bool Sprite::_edit_use_pivot() const {
return true;
}
+bool Sprite::_edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const {
+
+ return is_pixel_opaque(p_point);
+}
+
Rect2 Sprite::_edit_get_rect() const {
return get_rect();
}
@@ -65,6 +71,7 @@ Rect2 Sprite::_edit_get_rect() const {
bool Sprite::_edit_use_rect() const {
return texture.is_valid();
}
+#endif
Rect2 Sprite::get_anchorable_rect() const {
return get_rect();
@@ -305,11 +312,6 @@ int Sprite::get_hframes() const {
return hframes;
}
-bool Sprite::_edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const {
-
- return is_pixel_opaque(p_point);
-}
-
bool Sprite::is_pixel_opaque(const Point2 &p_point) const {
if (texture.is_null())
diff --git a/scene/2d/sprite.h b/scene/2d/sprite.h
index 2fd97f6611..d72bf3168d 100644
--- a/scene/2d/sprite.h
+++ b/scene/2d/sprite.h
@@ -67,6 +67,7 @@ protected:
virtual void _validate_property(PropertyInfo &property) const;
public:
+#ifdef TOOLS_ENABLED
virtual Dictionary _edit_get_state() const;
virtual void _edit_set_state(const Dictionary &p_state);
@@ -75,10 +76,11 @@ public:
virtual bool _edit_use_pivot() const;
virtual bool _edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const;
- bool is_pixel_opaque(const Point2 &p_point) const;
-
virtual Rect2 _edit_get_rect() const;
virtual bool _edit_use_rect() const;
+#endif
+
+ bool is_pixel_opaque(const Point2 &p_point) const;
void set_texture(const Ref<Texture> &p_texture);
Ref<Texture> get_texture() const;
diff --git a/scene/2d/tile_map.cpp b/scene/2d/tile_map.cpp
index 04ec13e415..b6db025d44 100644
--- a/scene/2d/tile_map.cpp
+++ b/scene/2d/tile_map.cpp
@@ -1282,6 +1282,7 @@ PoolVector<int> TileMap::_get_tile_data() const {
return data;
}
+#ifdef TOOLS_ENABLED
Rect2 TileMap::_edit_get_rect() const {
if (pending_update) {
const_cast<TileMap *>(this)->update_dirty_quadrants();
@@ -1290,6 +1291,7 @@ Rect2 TileMap::_edit_get_rect() const {
}
return rect_cache;
}
+#endif
void TileMap::set_collision_layer(uint32_t p_layer) {
diff --git a/scene/2d/tile_map.h b/scene/2d/tile_map.h
index 53bb696ba2..0875d197eb 100644
--- a/scene/2d/tile_map.h
+++ b/scene/2d/tile_map.h
@@ -244,7 +244,9 @@ public:
INVALID_CELL = -1
};
+#ifdef TOOLS_ENABLED
virtual Rect2 _edit_get_rect() const;
+#endif
void set_tileset(const Ref<TileSet> &p_tileset);
Ref<TileSet> get_tileset() const;
diff --git a/scene/2d/touch_screen_button.cpp b/scene/2d/touch_screen_button.cpp
index f6a888fa09..42d9f88a60 100644
--- a/scene/2d/touch_screen_button.cpp
+++ b/scene/2d/touch_screen_button.cpp
@@ -135,7 +135,9 @@ void TouchScreenButton::_notification(int p_what) {
return;
if (shape.is_valid()) {
Color draw_col = get_tree()->get_debug_collisions_color();
- Vector2 pos = shape_centered ? _edit_get_rect().size * 0.5f : Vector2();
+
+ Vector2 size = texture.is_null() ? shape->get_rect().size : texture->get_size();
+ Vector2 pos = shape_centered ? size * 0.5f : Vector2();
draw_set_transform_matrix(get_canvas_transform().translated(pos));
shape->draw(get_canvas_item(), draw_col);
}
@@ -251,9 +253,7 @@ void TouchScreenButton::_input(const Ref<InputEvent> &p_event) {
}
bool TouchScreenButton::_is_point_inside(const Point2 &p_point) {
-
Point2 coord = (get_global_transform_with_canvas()).affine_inverse().xform(p_point);
- Rect2 item_rect = _edit_get_rect();
bool touched = false;
bool check_rect = true;
@@ -261,7 +261,7 @@ bool TouchScreenButton::_is_point_inside(const Point2 &p_point) {
if (shape.is_valid()) {
check_rect = false;
- Transform2D xform = shape_centered ? Transform2D().translated(item_rect.size * 0.5f) : Transform2D();
+ Transform2D xform = shape_centered ? Transform2D().translated(shape->get_rect().size * 0.5f) : Transform2D();
touched = shape->collide(xform, unit_rect, Transform2D(0, coord + Vector2(0.5, 0.5)));
}
@@ -277,7 +277,7 @@ bool TouchScreenButton::_is_point_inside(const Point2 &p_point) {
if (!touched && check_rect) {
if (texture.is_valid())
- touched = item_rect.has_point(coord);
+ touched = Rect2(Size2(), texture->get_size()).has_point(coord);
}
return touched;
@@ -324,6 +324,7 @@ void TouchScreenButton::_release(bool p_exiting_tree) {
}
}
+#ifdef TOOLS_ENABLED
Rect2 TouchScreenButton::_edit_get_rect() const {
if (texture.is_null())
return CanvasItem::_edit_get_rect();
@@ -334,6 +335,7 @@ Rect2 TouchScreenButton::_edit_get_rect() const {
bool TouchScreenButton::_edit_use_rect() const {
return !texture.is_null();
}
+#endif
Rect2 TouchScreenButton::get_anchorable_rect() const {
if (texture.is_null())
diff --git a/scene/2d/touch_screen_button.h b/scene/2d/touch_screen_button.h
index 9c9fc6125a..28dba59402 100644
--- a/scene/2d/touch_screen_button.h
+++ b/scene/2d/touch_screen_button.h
@@ -74,6 +74,11 @@ protected:
static void _bind_methods();
public:
+#ifdef TOOLS_ENABLED
+ virtual Rect2 _edit_get_rect() const;
+ virtual bool _edit_use_rect() const;
+#endif
+
void set_texture(const Ref<Texture> &p_texture);
Ref<Texture> get_texture() const;
@@ -103,8 +108,6 @@ public:
bool is_pressed() const;
- virtual Rect2 _edit_get_rect() const;
- virtual bool _edit_use_rect() const;
virtual Rect2 get_anchorable_rect() const;
TouchScreenButton();
diff --git a/scene/2d/visibility_notifier_2d.cpp b/scene/2d/visibility_notifier_2d.cpp
index 223e57f39f..0ac725b7dd 100644
--- a/scene/2d/visibility_notifier_2d.cpp
+++ b/scene/2d/visibility_notifier_2d.cpp
@@ -38,6 +38,16 @@
#include "scene/main/viewport.h"
#include "scene/scene_string_names.h"
+#ifdef TOOLS_ENABLED
+Rect2 VisibilityNotifier2D::_edit_get_rect() const {
+ return rect;
+}
+
+bool VisibilityNotifier2D::_edit_use_rect() const {
+ return true;
+}
+#endif
+
void VisibilityNotifier2D::_enter_viewport(Viewport *p_viewport) {
ERR_FAIL_COND(viewports.has(p_viewport));
@@ -84,15 +94,6 @@ void VisibilityNotifier2D::set_rect(const Rect2 &p_rect) {
_change_notify("rect");
}
-Rect2 VisibilityNotifier2D::_edit_get_rect() const {
-
- return rect;
-}
-
-bool VisibilityNotifier2D::_edit_use_rect() const {
- return true;
-}
-
Rect2 VisibilityNotifier2D::get_rect() const {
return rect;
diff --git a/scene/2d/visibility_notifier_2d.h b/scene/2d/visibility_notifier_2d.h
index f9d4c238eb..a3b79d29e9 100644
--- a/scene/2d/visibility_notifier_2d.h
+++ b/scene/2d/visibility_notifier_2d.h
@@ -55,8 +55,10 @@ protected:
static void _bind_methods();
public:
+#ifdef TOOLS_ENABLED
virtual Rect2 _edit_get_rect() const;
virtual bool _edit_use_rect() const;
+#endif
void set_rect(const Rect2 &p_rect);
Rect2 get_rect() const;
diff --git a/scene/3d/camera.cpp b/scene/3d/camera.cpp
index 289dc0ba07..3a30755f7f 100644
--- a/scene/3d/camera.cpp
+++ b/scene/3d/camera.cpp
@@ -398,9 +398,9 @@ Vector3 Camera::project_position(const Point2 &p_point, float p_z_depth) const {
CameraMatrix cm;
if (mode == PROJECTION_ORTHOGONAL)
- cm.set_orthogonal(size, viewport_size.aspect(), near, far, keep_aspect == KEEP_WIDTH);
+ cm.set_orthogonal(size, viewport_size.aspect(), p_z_depth, far, keep_aspect == KEEP_WIDTH);
else
- cm.set_perspective(fov, viewport_size.aspect(), near, far, keep_aspect == KEEP_WIDTH);
+ cm.set_perspective(fov, viewport_size.aspect(), p_z_depth, far, keep_aspect == KEEP_WIDTH);
Size2 vp_size;
cm.get_viewport_size(vp_size.x, vp_size.y);
diff --git a/scene/3d/cpu_particles.cpp b/scene/3d/cpu_particles.cpp
index 0ac424b09e..aa7a413548 100644
--- a/scene/3d/cpu_particles.cpp
+++ b/scene/3d/cpu_particles.cpp
@@ -405,7 +405,7 @@ bool CPUParticles::get_particle_flag(Flags p_flag) const {
}
void CPUParticles::set_emission_shape(EmissionShape p_shape) {
-
+ ERR_FAIL_INDEX(p_shape, EMISSION_SHAPE_MAX);
emission_shape = p_shape;
}
@@ -784,6 +784,9 @@ void CPUParticles::_particles_process(float p_delta) {
p.base_color = emission_colors.get(random_idx);
}
} break;
+ case EMISSION_SHAPE_MAX: { // Max value for validity check.
+ break;
+ }
}
if (!local_coords) {
@@ -1488,6 +1491,7 @@ void CPUParticles::_bind_methods() {
BIND_ENUM_CONSTANT(EMISSION_SHAPE_BOX);
BIND_ENUM_CONSTANT(EMISSION_SHAPE_POINTS);
BIND_ENUM_CONSTANT(EMISSION_SHAPE_DIRECTED_POINTS);
+ BIND_ENUM_CONSTANT(EMISSION_SHAPE_MAX);
}
CPUParticles::CPUParticles() {
diff --git a/scene/3d/cpu_particles.h b/scene/3d/cpu_particles.h
index 18f9718e70..d5a549b976 100644
--- a/scene/3d/cpu_particles.h
+++ b/scene/3d/cpu_particles.h
@@ -75,6 +75,7 @@ public:
EMISSION_SHAPE_BOX,
EMISSION_SHAPE_POINTS,
EMISSION_SHAPE_DIRECTED_POINTS,
+ EMISSION_SHAPE_MAX
};
private:
diff --git a/scene/3d/physics_body.cpp b/scene/3d/physics_body.cpp
index 44dc3d0c26..caeae90238 100644
--- a/scene/3d/physics_body.cpp
+++ b/scene/3d/physics_body.cpp
@@ -1140,7 +1140,7 @@ bool KinematicBody::move_and_collide(const Vector3 &p_motion, bool p_infinite_in
//so, if you pass 45 as limit, avoid numerical precision errors when angle is 45.
#define FLOOR_ANGLE_THRESHOLD 0.01
-Vector3 KinematicBody::move_and_slide(const Vector3 &p_linear_velocity, const Vector3 &p_floor_direction, bool p_stop_on_slope, int p_max_slides, float p_floor_max_angle, bool p_infinite_inertia) {
+Vector3 KinematicBody::move_and_slide(const Vector3 &p_linear_velocity, const Vector3 &p_up_direction, bool p_stop_on_slope, int p_max_slides, float p_floor_max_angle, bool p_infinite_inertia) {
Vector3 body_velocity = p_linear_velocity;
Vector3 body_velocity_normal = body_velocity.normalized();
@@ -1151,23 +1151,15 @@ Vector3 KinematicBody::move_and_slide(const Vector3 &p_linear_velocity, const Ve
}
}
- Vector3 current_floor_velocity = floor_velocity;
- if (on_floor && on_floor_body.is_valid()) {
- //this approach makes sure there is less delay between the actual body velocity and the one we saved
- PhysicsDirectBodyState *bs = PhysicsServer::get_singleton()->body_get_direct_state(on_floor_body);
- if (bs) {
- current_floor_velocity = bs->get_linear_velocity();
- }
- }
-
// Hack in order to work with calling from _process as well as from _physics_process; calling from thread is risky
- Vector3 motion = (current_floor_velocity + body_velocity) * (Engine::get_singleton()->is_in_physics_frame() ? get_physics_process_delta_time() : get_process_delta_time());
+ Vector3 motion = (floor_velocity + body_velocity) * (Engine::get_singleton()->is_in_physics_frame() ? get_physics_process_delta_time() : get_process_delta_time());
on_floor = false;
on_floor_body = RID();
on_ceiling = false;
on_wall = false;
colliders.clear();
+ floor_normal = Vector3();
floor_velocity = Vector3();
while (p_max_slides) {
@@ -1196,25 +1188,26 @@ Vector3 KinematicBody::move_and_slide(const Vector3 &p_linear_velocity, const Ve
colliders.push_back(collision);
motion = collision.remainder;
- if (p_floor_direction == Vector3()) {
+ if (p_up_direction == Vector3()) {
//all is a wall
on_wall = true;
} else {
- if (Math::acos(collision.normal.dot(p_floor_direction)) <= p_floor_max_angle + FLOOR_ANGLE_THRESHOLD) { //floor
+ if (Math::acos(collision.normal.dot(p_up_direction)) <= p_floor_max_angle + FLOOR_ANGLE_THRESHOLD) { //floor
on_floor = true;
+ floor_normal = collision.normal;
on_floor_body = collision.collider_rid;
floor_velocity = collision.collider_vel;
if (p_stop_on_slope) {
- if ((body_velocity_normal + p_floor_direction).length() < 0.01 && collision.travel.length() < 1) {
+ if ((body_velocity_normal + p_up_direction).length() < 0.01 && collision.travel.length() < 1) {
Transform gt = get_global_transform();
- gt.origin -= collision.travel.slide(p_floor_direction);
+ gt.origin -= collision.travel.slide(p_up_direction);
set_global_transform(gt);
return Vector3();
}
}
- } else if (Math::acos(collision.normal.dot(-p_floor_direction)) <= p_floor_max_angle + FLOOR_ANGLE_THRESHOLD) { //ceiling
+ } else if (Math::acos(collision.normal.dot(-p_up_direction)) <= p_floor_max_angle + FLOOR_ANGLE_THRESHOLD) { //ceiling
on_ceiling = true;
} else {
on_wall = true;
@@ -1241,11 +1234,11 @@ Vector3 KinematicBody::move_and_slide(const Vector3 &p_linear_velocity, const Ve
return body_velocity;
}
-Vector3 KinematicBody::move_and_slide_with_snap(const Vector3 &p_linear_velocity, const Vector3 &p_snap, const Vector3 &p_floor_direction, bool p_stop_on_slope, int p_max_slides, float p_floor_max_angle, bool p_infinite_inertia) {
+Vector3 KinematicBody::move_and_slide_with_snap(const Vector3 &p_linear_velocity, const Vector3 &p_snap, const Vector3 &p_up_direction, bool p_stop_on_slope, int p_max_slides, float p_floor_max_angle, bool p_infinite_inertia) {
bool was_on_floor = on_floor;
- Vector3 ret = move_and_slide(p_linear_velocity, p_floor_direction, p_stop_on_slope, p_max_slides, p_floor_max_angle, p_infinite_inertia);
+ Vector3 ret = move_and_slide(p_linear_velocity, p_up_direction, p_stop_on_slope, p_max_slides, p_floor_max_angle, p_infinite_inertia);
if (!was_on_floor || p_snap == Vector3()) {
return ret;
}
@@ -1256,15 +1249,16 @@ Vector3 KinematicBody::move_and_slide_with_snap(const Vector3 &p_linear_velocity
if (move_and_collide(p_snap, p_infinite_inertia, col, false, true)) {
bool apply = true;
- if (p_floor_direction != Vector3()) {
- if (Math::acos(p_floor_direction.normalized().dot(col.normal)) < p_floor_max_angle) {
+ if (p_up_direction != Vector3()) {
+ if (Math::acos(p_up_direction.normalized().dot(col.normal)) < p_floor_max_angle) {
on_floor = true;
+ floor_normal = col.normal;
on_floor_body = col.collider_rid;
floor_velocity = col.collider_vel;
if (p_stop_on_slope) {
// move and collide may stray the object a bit because of pre un-stucking,
// so only ensure that motion happens on floor direction in this case.
- col.travel = col.travel.project(p_floor_direction);
+ col.travel = col.travel.project(p_up_direction);
}
} else {
apply = false; //snapped with floor direction, but did not snap to a floor, do not snap.
@@ -1293,6 +1287,11 @@ bool KinematicBody::is_on_ceiling() const {
return on_ceiling;
}
+Vector3 KinematicBody::get_floor_normal() const {
+
+ return floor_normal;
+}
+
Vector3 KinematicBody::get_floor_velocity() const {
return floor_velocity;
@@ -1401,14 +1400,15 @@ void KinematicBody::_notification(int p_what) {
void KinematicBody::_bind_methods() {
ClassDB::bind_method(D_METHOD("move_and_collide", "rel_vec", "infinite_inertia", "exclude_raycast_shapes", "test_only"), &KinematicBody::_move, DEFVAL(true), DEFVAL(true), DEFVAL(false));
- ClassDB::bind_method(D_METHOD("move_and_slide", "linear_velocity", "floor_normal", "stop_on_slope", "max_slides", "floor_max_angle", "infinite_inertia"), &KinematicBody::move_and_slide, DEFVAL(Vector3(0, 0, 0)), DEFVAL(false), DEFVAL(4), DEFVAL(Math::deg2rad((float)45)), DEFVAL(true));
- ClassDB::bind_method(D_METHOD("move_and_slide_with_snap", "linear_velocity", "snap", "floor_normal", "stop_on_slope", "max_slides", "floor_max_angle", "infinite_inertia"), &KinematicBody::move_and_slide_with_snap, DEFVAL(Vector3(0, 0, 0)), DEFVAL(false), DEFVAL(4), DEFVAL(Math::deg2rad((float)45)), DEFVAL(true));
+ ClassDB::bind_method(D_METHOD("move_and_slide", "linear_velocity", "up_direction", "stop_on_slope", "max_slides", "floor_max_angle", "infinite_inertia"), &KinematicBody::move_and_slide, DEFVAL(Vector3(0, 0, 0)), DEFVAL(false), DEFVAL(4), DEFVAL(Math::deg2rad((float)45)), DEFVAL(true));
+ ClassDB::bind_method(D_METHOD("move_and_slide_with_snap", "linear_velocity", "snap", "up_direction", "stop_on_slope", "max_slides", "floor_max_angle", "infinite_inertia"), &KinematicBody::move_and_slide_with_snap, DEFVAL(Vector3(0, 0, 0)), DEFVAL(false), DEFVAL(4), DEFVAL(Math::deg2rad((float)45)), DEFVAL(true));
ClassDB::bind_method(D_METHOD("test_move", "from", "rel_vec", "infinite_inertia"), &KinematicBody::test_move, DEFVAL(true));
ClassDB::bind_method(D_METHOD("is_on_floor"), &KinematicBody::is_on_floor);
ClassDB::bind_method(D_METHOD("is_on_ceiling"), &KinematicBody::is_on_ceiling);
ClassDB::bind_method(D_METHOD("is_on_wall"), &KinematicBody::is_on_wall);
+ ClassDB::bind_method(D_METHOD("get_floor_normal"), &KinematicBody::get_floor_normal);
ClassDB::bind_method(D_METHOD("get_floor_velocity"), &KinematicBody::get_floor_velocity);
ClassDB::bind_method(D_METHOD("set_axis_lock", "axis", "lock"), &KinematicBody::set_axis_lock);
diff --git a/scene/3d/physics_body.h b/scene/3d/physics_body.h
index 06b31804b2..05bcbe22f0 100644
--- a/scene/3d/physics_body.h
+++ b/scene/3d/physics_body.h
@@ -300,6 +300,7 @@ private:
float margin;
+ Vector3 floor_normal;
Vector3 floor_velocity;
RID on_floor_body;
bool on_floor;
@@ -330,11 +331,12 @@ public:
void set_safe_margin(float p_margin);
float get_safe_margin() const;
- Vector3 move_and_slide(const Vector3 &p_linear_velocity, const Vector3 &p_floor_direction = Vector3(0, 0, 0), bool p_stop_on_slope = false, int p_max_slides = 4, float p_floor_max_angle = Math::deg2rad((float)45), bool p_infinite_inertia = true);
- Vector3 move_and_slide_with_snap(const Vector3 &p_linear_velocity, const Vector3 &p_snap, const Vector3 &p_floor_direction = Vector3(0, 0, 0), bool p_stop_on_slope = false, int p_max_slides = 4, float p_floor_max_angle = Math::deg2rad((float)45), bool p_infinite_inertia = true);
+ Vector3 move_and_slide(const Vector3 &p_linear_velocity, const Vector3 &p_up_direction = Vector3(0, 0, 0), bool p_stop_on_slope = false, int p_max_slides = 4, float p_floor_max_angle = Math::deg2rad((float)45), bool p_infinite_inertia = true);
+ Vector3 move_and_slide_with_snap(const Vector3 &p_linear_velocity, const Vector3 &p_snap, const Vector3 &p_up_direction = Vector3(0, 0, 0), bool p_stop_on_slope = false, int p_max_slides = 4, float p_floor_max_angle = Math::deg2rad((float)45), bool p_infinite_inertia = true);
bool is_on_floor() const;
bool is_on_wall() const;
bool is_on_ceiling() const;
+ Vector3 get_floor_normal() const;
Vector3 get_floor_velocity() const;
int get_slide_count() const;
diff --git a/scene/animation/skeleton_ik.cpp b/scene/animation/skeleton_ik.cpp
index 99a266af0d..518c243dd0 100644
--- a/scene/animation/skeleton_ik.cpp
+++ b/scene/animation/skeleton_ik.cpp
@@ -320,7 +320,7 @@ void FabrikInverseKinematic::solve(Task *p_task, real_t blending_delta, bool ove
new_bone_pose.basis = new_bone_pose.basis * p_task->chain.tips[0].end_effector->goal_transform.basis;
}
- p_task->skeleton->set_bone_global_pose_override(ci->bone, new_bone_pose, 1.0);
+ p_task->skeleton->set_bone_global_pose_override(ci->bone, new_bone_pose, 1.0, true);
if (!ci->children.empty())
ci = &ci->children.write[0];
diff --git a/scene/gui/base_button.cpp b/scene/gui/base_button.cpp
index 65912c1c07..b2020d44e8 100644
--- a/scene/gui/base_button.cpp
+++ b/scene/gui/base_button.cpp
@@ -165,7 +165,7 @@ void BaseButton::on_action_event(Ref<InputEvent> p_event) {
_pressed();
}
} else {
- if (!p_event->is_pressed()) {
+ if ((p_event->is_pressed() && action_mode == ACTION_MODE_BUTTON_PRESS) || (!p_event->is_pressed() && action_mode == ACTION_MODE_BUTTON_RELEASE)) {
_pressed();
}
}
diff --git a/scene/gui/center_container.cpp b/scene/gui/center_container.cpp
index 9f4353ceb6..64d6885bc8 100644
--- a/scene/gui/center_container.cpp
+++ b/scene/gui/center_container.cpp
@@ -54,7 +54,13 @@ Size2 CenterContainer::get_minimum_size() const {
void CenterContainer::set_use_top_left(bool p_enable) {
+ if (use_top_left == p_enable) {
+ return;
+ }
+
use_top_left = p_enable;
+
+ minimum_size_changed();
queue_sort();
}
diff --git a/scene/gui/color_picker.cpp b/scene/gui/color_picker.cpp
index bab8d9167b..01f4070883 100644
--- a/scene/gui/color_picker.cpp
+++ b/scene/gui/color_picker.cpp
@@ -573,9 +573,7 @@ void ColorPicker::_preset_input(const Ref<InputEvent> &p_event) {
}
if (index < 0 || index >= presets.size())
return;
- preset->set_tooltip("Color: #" + presets[index].to_html(presets[index].a < 1) + "\n"
- "LMB: Set color\n"
- "RMB: Remove preset");
+ preset->set_tooltip(vformat(RTR("Color: #%s\nLMB: Set color\nRMB: Remove preset"), presets[index].to_html(presets[index].a < 1)));
}
}
diff --git a/scene/gui/control.cpp b/scene/gui/control.cpp
index 5e656eea70..4f499af186 100644
--- a/scene/gui/control.cpp
+++ b/scene/gui/control.cpp
@@ -47,6 +47,7 @@
#include "editor/plugins/canvas_item_editor_plugin.h"
#endif
+#ifdef TOOLS_ENABLED
Dictionary Control::_edit_get_state() const {
Dictionary s;
@@ -155,6 +156,11 @@ bool Control::_edit_use_pivot() const {
return true;
}
+Size2 Control::_edit_get_minimum_size() const {
+ return get_combined_minimum_size();
+}
+#endif
+
void Control::set_custom_minimum_size(const Size2 &p_custom) {
if (p_custom == data.custom_minimum_size)
@@ -193,11 +199,6 @@ Size2 Control::get_combined_minimum_size() const {
return data.minimum_size_cache;
}
-Size2 Control::_edit_get_minimum_size() const {
-
- return get_combined_minimum_size();
-}
-
Transform2D Control::_get_internal_transform() const {
Transform2D rot_scale;
@@ -2681,6 +2682,11 @@ Vector2 Control::get_pivot_offset() const {
void Control::set_scale(const Vector2 &p_scale) {
data.scale = p_scale;
+ // Avoid having 0 scale values, can lead to errors in physics and rendering.
+ if (data.scale.x == 0)
+ data.scale.x = CMP_EPSILON;
+ if (data.scale.y == 0)
+ data.scale.y = CMP_EPSILON;
update();
_notify_transform();
}
diff --git a/scene/gui/control.h b/scene/gui/control.h
index a9831b9793..357858beb6 100644
--- a/scene/gui/control.h
+++ b/scene/gui/control.h
@@ -279,6 +279,7 @@ public:
};
/* EDITOR */
+#ifdef TOOLS_ENABLED
virtual Dictionary _edit_get_state() const;
virtual void _edit_set_state(const Dictionary &p_state);
@@ -301,6 +302,7 @@ public:
virtual bool _edit_use_pivot() const;
virtual Size2 _edit_get_minimum_size() const;
+#endif
void accept_event();
diff --git a/scene/gui/graph_edit.cpp b/scene/gui/graph_edit.cpp
index d1650fea1e..00ce57eb04 100644
--- a/scene/gui/graph_edit.cpp
+++ b/scene/gui/graph_edit.cpp
@@ -200,6 +200,13 @@ void GraphEdit::_update_scroll() {
else
v_scroll->show();
+ Size2 hmin = h_scroll->get_combined_minimum_size();
+ Size2 vmin = v_scroll->get_combined_minimum_size();
+
+ // Avoid scrollbar overlapping.
+ h_scroll->set_anchor_and_margin(MARGIN_RIGHT, ANCHOR_END, v_scroll->is_visible() ? -vmin.width : 0);
+ v_scroll->set_anchor_and_margin(MARGIN_BOTTOM, ANCHOR_END, h_scroll->is_visible() ? -hmin.height : 0);
+
set_block_minimum_size_adjust(false);
if (!awaiting_scroll_offset_update) {
@@ -286,15 +293,15 @@ void GraphEdit::_notification(int p_what) {
Size2 hmin = h_scroll->get_combined_minimum_size();
Size2 vmin = v_scroll->get_combined_minimum_size();
- v_scroll->set_anchor_and_margin(MARGIN_LEFT, ANCHOR_END, -vmin.width);
- v_scroll->set_anchor_and_margin(MARGIN_RIGHT, ANCHOR_END, 0);
- v_scroll->set_anchor_and_margin(MARGIN_TOP, ANCHOR_BEGIN, 0);
- v_scroll->set_anchor_and_margin(MARGIN_BOTTOM, ANCHOR_END, 0);
-
h_scroll->set_anchor_and_margin(MARGIN_LEFT, ANCHOR_BEGIN, 0);
h_scroll->set_anchor_and_margin(MARGIN_RIGHT, ANCHOR_END, 0);
h_scroll->set_anchor_and_margin(MARGIN_TOP, ANCHOR_END, -hmin.height);
h_scroll->set_anchor_and_margin(MARGIN_BOTTOM, ANCHOR_END, 0);
+
+ v_scroll->set_anchor_and_margin(MARGIN_LEFT, ANCHOR_END, -vmin.width);
+ v_scroll->set_anchor_and_margin(MARGIN_RIGHT, ANCHOR_END, 0);
+ v_scroll->set_anchor_and_margin(MARGIN_TOP, ANCHOR_BEGIN, 0);
+ v_scroll->set_anchor_and_margin(MARGIN_BOTTOM, ANCHOR_END, 0);
}
if (p_what == NOTIFICATION_DRAW) {
@@ -777,14 +784,8 @@ void GraphEdit::_top_layer_draw() {
}
if (box_selecting) {
- top_layer->draw_rect(
- box_selecting_rect,
- get_color("box_selection_fill_color", "Editor"));
-
- top_layer->draw_rect(
- box_selecting_rect,
- get_color("box_selection_stroke_color", "Editor"),
- false);
+ top_layer->draw_rect(box_selecting_rect, get_color("selection_fill"));
+ top_layer->draw_rect(box_selecting_rect, get_color("selection_stroke"), false);
}
}
@@ -1358,6 +1359,7 @@ GraphEdit::GraphEdit() {
v_scroll = memnew(VScrollBar);
v_scroll->set_name("_v_scroll");
top_layer->add_child(v_scroll);
+
updating = false;
connecting = false;
right_disconnects = false;
diff --git a/scene/gui/item_list.cpp b/scene/gui/item_list.cpp
index 2a812caf9a..526950dbb3 100644
--- a/scene/gui/item_list.cpp
+++ b/scene/gui/item_list.cpp
@@ -993,7 +993,7 @@ void ItemList::_notification(int p_what) {
}
//ensure_selected_visible needs to be checked before we draw the list.
- if (ensure_selected_visible && current >= 0 && current <= items.size()) {
+ if (ensure_selected_visible && current >= 0 && current < items.size()) {
Rect2 r = items[current].rect_cache;
int from = scroll_bar->get_value();
diff --git a/scene/gui/label.cpp b/scene/gui/label.cpp
index 11172ac7a9..77913efd1c 100644
--- a/scene/gui/label.cpp
+++ b/scene/gui/label.cpp
@@ -35,9 +35,17 @@
void Label::set_autowrap(bool p_autowrap) {
+ if (autowrap == p_autowrap) {
+ return;
+ }
+
autowrap = p_autowrap;
word_cache_dirty = true;
update();
+
+ if (clip) {
+ minimum_size_changed();
+ }
}
bool Label::has_autowrap() const {
@@ -103,8 +111,7 @@ void Label::_notification(int p_what) {
int lines_visible = (size.y + line_spacing) / font_h;
- // ceiling to ensure autowrapping does not cut text
- int space_w = Math::ceil(font->get_char_size(' ').width);
+ real_t space_w = font->get_char_size(' ').width;
int chars_total = 0;
int vbegin = 0, vsep = 0;
@@ -225,6 +232,7 @@ void Label::_notification(int p_what) {
return;
}
if (from->space_count) {
+ chars_total += from->space_count;
/* spacing */
x_ofs += space_w * from->space_count;
if (can_fill && align == ALIGN_FILL && spaces) {
@@ -313,8 +321,8 @@ Size2 Label::get_minimum_size() const {
int Label::get_longest_line_width() const {
Ref<Font> font = get_font("font");
- int max_line_width = 0;
- int line_width = 0;
+ real_t max_line_width = 0;
+ real_t line_width = 0;
for (int i = 0; i < xl_text.size(); i++) {
@@ -332,8 +340,7 @@ int Label::get_longest_line_width() const {
}
} else {
- // ceiling to ensure autowrapping does not cut text
- int char_width = Math::ceil(font->get_char_size(current, xl_text[i + 1]).width);
+ real_t char_width = font->get_char_size(current, xl_text[i + 1]).width;
line_width += char_width;
}
}
@@ -341,7 +348,8 @@ int Label::get_longest_line_width() const {
if (line_width > max_line_width)
max_line_width = line_width;
- return max_line_width;
+ // ceiling to ensure autowrapping does not cut text
+ return Math::ceil(max_line_width);
}
int Label::get_line_count() const {
@@ -388,12 +396,11 @@ void Label::regenerate_word_cache() {
Ref<Font> font = get_font("font");
- int current_word_size = 0;
+ real_t current_word_size = 0;
int word_pos = 0;
- int line_width = 0;
+ real_t line_width = 0;
int space_count = 0;
- // ceiling to ensure autowrapping does not cut text
- int space_width = Math::ceil(font->get_char_size(' ').width);
+ real_t space_width = font->get_char_size(' ').width;
int line_spacing = get_constant("line_spacing");
line_count = 1;
total_char_cache = 0;
@@ -413,7 +420,7 @@ void Label::regenerate_word_cache() {
bool separatable = (current >= 0x2E08 && current <= 0xFAFF) || (current >= 0xFE30 && current <= 0xFE4F);
//current>=33 && (current < 65||current >90) && (current<97||current>122) && (current<48||current>57);
bool insert_newline = false;
- int char_width = 0;
+ real_t char_width = 0;
if (current < 33) {
@@ -454,8 +461,7 @@ void Label::regenerate_word_cache() {
if (current_word_size == 0) {
word_pos = i;
}
- // ceiling to ensure autowrapping does not cut text
- char_width = Math::ceil(font->get_char_size(current, xl_text[i + 1]).width);
+ char_width = font->get_char_size(current, xl_text[i + 1]).width;
current_word_size += char_width;
line_width += char_width;
total_char_cache++;
diff --git a/scene/gui/line_edit.cpp b/scene/gui/line_edit.cpp
index 8f5f6beac3..0f3328dac5 100644
--- a/scene/gui/line_edit.cpp
+++ b/scene/gui/line_edit.cpp
@@ -557,8 +557,11 @@ void LineEdit::_gui_input(Ref<InputEvent> p_event) {
if (editable) {
selection_delete();
CharType ucodestr[2] = { (CharType)k->get_unicode(), 0 };
+ int prev_len = text.length();
append_at_cursor(ucodestr);
- _text_changed();
+ if (text.length() != prev_len) {
+ _text_changed();
+ }
accept_event();
}
@@ -961,11 +964,12 @@ void LineEdit::paste_text() {
if (paste_buffer != "") {
+ int prev_len = text.length();
if (selection.enabled) selection_delete();
append_at_cursor(paste_buffer);
if (!text_changed_dirty) {
- if (is_inside_tree()) {
+ if (is_inside_tree() && text.length() != prev_len) {
MessageQueue::get_singleton()->push_call(this, "_text_changed");
}
text_changed_dirty = true;
@@ -1189,7 +1193,7 @@ void LineEdit::delete_char() {
set_cursor_position(get_cursor_position() - 1);
if (align == ALIGN_CENTER || align == ALIGN_RIGHT) {
- window_pos = CLAMP(window_pos - 1, 0, text.length() - 1);
+ window_pos = CLAMP(window_pos - 1, 0, MAX(text.length() - 1, 0));
}
_text_changed();
@@ -1220,7 +1224,7 @@ void LineEdit::delete_text(int p_from_column, int p_to_column) {
}
if (align == ALIGN_CENTER || align == ALIGN_RIGHT) {
- window_pos = CLAMP(window_pos - (p_to_column - p_from_column), 0, text.length() - 1);
+ window_pos = CLAMP(window_pos - (p_to_column - p_from_column), 0, MAX(text.length() - 1, 0));
}
if (!text_changed_dirty) {
@@ -1235,6 +1239,11 @@ void LineEdit::set_text(String p_text) {
clear_internal();
append_at_cursor(p_text);
+
+ if (expand_to_text_length) {
+ minimum_size_changed();
+ }
+
update();
cursor_pos = 0;
window_pos = 0;
@@ -1362,6 +1371,8 @@ void LineEdit::append_at_cursor(String p_text) {
String post = text.substr(cursor_pos, text.length() - cursor_pos);
text = pre + p_text + post;
set_cursor_position(cursor_pos + p_text.length());
+ } else {
+ emit_signal("text_change_rejected");
}
}
@@ -1476,6 +1487,7 @@ void LineEdit::set_editable(bool p_editable) {
editable = p_editable;
_generate_context_menu();
+ minimum_size_changed();
update();
}
@@ -1611,7 +1623,11 @@ bool LineEdit::get_expand_to_text_length() const {
}
void LineEdit::set_clear_button_enabled(bool p_enabled) {
+ if (clear_button_enabled == p_enabled) {
+ return;
+ }
clear_button_enabled = p_enabled;
+ minimum_size_changed();
update();
}
@@ -1647,6 +1663,7 @@ void LineEdit::set_right_icon(const Ref<Texture> &p_icon) {
return;
}
right_icon = p_icon;
+ minimum_size_changed();
update();
}
@@ -1781,6 +1798,7 @@ void LineEdit::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_right_icon"), &LineEdit::get_right_icon);
ADD_SIGNAL(MethodInfo("text_changed", PropertyInfo(Variant::STRING, "new_text")));
+ ADD_SIGNAL(MethodInfo("text_change_rejected"));
ADD_SIGNAL(MethodInfo("text_entered", PropertyInfo(Variant::STRING, "new_text")));
BIND_ENUM_CONSTANT(ALIGN_LEFT);
diff --git a/scene/gui/rich_text_label.cpp b/scene/gui/rich_text_label.cpp
index 5b7d7403ae..6c2928c65c 100644
--- a/scene/gui/rich_text_label.cpp
+++ b/scene/gui/rich_text_label.cpp
@@ -253,24 +253,25 @@ int RichTextLabel::_process_line(ItemFrame *p_frame, const Vector2 &p_ofs, int &
} \
}
-#define ENSURE_WIDTH(m_width) \
- if (p_mode == PROCESS_CACHE) { \
- l.maximum_width = MAX(l.maximum_width, MIN(p_width, wofs + m_width)); \
- l.minimum_width = MAX(l.minimum_width, m_width); \
- } \
- if (wofs + m_width > p_width) { \
- line_wrapped = true; \
- if (p_mode == PROCESS_CACHE) { \
- if (spaces > 0) \
- spaces -= 1; \
- } \
- if (p_mode == PROCESS_POINTER && r_click_item && p_click_pos.y >= p_ofs.y + y && p_click_pos.y <= p_ofs.y + y + lh && p_click_pos.x > p_ofs.x + wofs) { \
- if (r_outside) *r_outside = true; \
- *r_click_item = it; \
- *r_click_char = rchar; \
- RETURN; \
- } \
- NEW_LINE \
+#define ENSURE_WIDTH(m_width) \
+ if (p_mode == PROCESS_CACHE) { \
+ l.maximum_width = MAX(l.maximum_width, MIN(p_width, wofs + m_width)); \
+ l.minimum_width = MAX(l.minimum_width, m_width); \
+ } \
+ if (wofs + m_width > p_width) { \
+ line_wrapped = true; \
+ if (p_mode == PROCESS_CACHE) { \
+ if (spaces > 0) \
+ spaces -= 1; \
+ } \
+ const bool x_in_range = (p_click_pos.x > p_ofs.x + wofs) && (!p_frame->cell || p_click_pos.x < p_ofs.x + p_width); \
+ if (p_mode == PROCESS_POINTER && r_click_item && p_click_pos.y >= p_ofs.y + y && p_click_pos.y <= p_ofs.y + y + lh && x_in_range) { \
+ if (r_outside) *r_outside = true; \
+ *r_click_item = it; \
+ *r_click_char = rchar; \
+ RETURN; \
+ } \
+ NEW_LINE \
}
#define ADVANCE(m_width) \
@@ -934,6 +935,14 @@ void RichTextLabel::_notification(int p_what) {
switch (p_what) {
+ case NOTIFICATION_MOUSE_EXIT: {
+ if (meta_hovering) {
+ meta_hovering = NULL;
+ emit_signal("meta_hover_ended", current_meta);
+ current_meta = false;
+ update();
+ }
+ } break;
case NOTIFICATION_RESIZED: {
main->first_invalid_line = 0; //invalidate ALL
@@ -1063,10 +1072,10 @@ Control::CursorShape RichTextLabel::get_cursor_shape(const Point2 &p_pos) const
int line = 0;
Item *item = NULL;
+ bool outside;
+ ((RichTextLabel *)(this))->_find_click(main, p_pos, &item, &line, &outside);
- ((RichTextLabel *)(this))->_find_click(main, p_pos, &item, &line);
-
- if (item && ((RichTextLabel *)(this))->_find_meta(item, NULL))
+ if (item && !outside && ((RichTextLabel *)(this))->_find_meta(item, NULL))
return CURSOR_POINTING_HAND;
return CURSOR_ARROW;
diff --git a/scene/gui/scroll_container.cpp b/scene/gui/scroll_container.cpp
index dc1183df74..509e6d19f6 100644
--- a/scene/gui/scroll_container.cpp
+++ b/scene/gui/scroll_container.cpp
@@ -219,16 +219,16 @@ void ScrollContainer::_update_scrollbar_position() {
Size2 hmin = h_scroll->get_combined_minimum_size();
Size2 vmin = v_scroll->get_combined_minimum_size();
- v_scroll->set_anchor_and_margin(MARGIN_LEFT, ANCHOR_END, -vmin.width);
- v_scroll->set_anchor_and_margin(MARGIN_RIGHT, ANCHOR_END, 0);
- v_scroll->set_anchor_and_margin(MARGIN_TOP, ANCHOR_BEGIN, 0);
- v_scroll->set_anchor_and_margin(MARGIN_BOTTOM, ANCHOR_END, 0);
-
h_scroll->set_anchor_and_margin(MARGIN_LEFT, ANCHOR_BEGIN, 0);
h_scroll->set_anchor_and_margin(MARGIN_RIGHT, ANCHOR_END, 0);
h_scroll->set_anchor_and_margin(MARGIN_TOP, ANCHOR_END, -hmin.height);
h_scroll->set_anchor_and_margin(MARGIN_BOTTOM, ANCHOR_END, 0);
+ v_scroll->set_anchor_and_margin(MARGIN_LEFT, ANCHOR_END, -vmin.width);
+ v_scroll->set_anchor_and_margin(MARGIN_RIGHT, ANCHOR_END, 0);
+ v_scroll->set_anchor_and_margin(MARGIN_TOP, ANCHOR_BEGIN, 0);
+ v_scroll->set_anchor_and_margin(MARGIN_BOTTOM, ANCHOR_END, 0);
+
h_scroll->raise();
v_scroll->raise();
}
@@ -317,6 +317,7 @@ void ScrollContainer::_notification(int p_what) {
r.position += ofs;
fit_child_in_rect(c, r);
}
+
update();
};
@@ -408,13 +409,17 @@ void ScrollContainer::update_scrollbars() {
Size2 hmin;
Size2 vmin;
- if (scroll_h) hmin = h_scroll->get_combined_minimum_size();
- if (scroll_v) vmin = v_scroll->get_combined_minimum_size();
+ if (scroll_h) {
+ hmin = h_scroll->get_combined_minimum_size();
+ }
+ if (scroll_v) {
+ vmin = v_scroll->get_combined_minimum_size();
+ }
Size2 min = child_max_size;
- bool hide_scroll_v = !scroll_v || min.height <= size.height - hmin.height;
- bool hide_scroll_h = !scroll_h || min.width <= size.width - vmin.width;
+ bool hide_scroll_v = !scroll_v || min.height <= size.height;
+ bool hide_scroll_h = !scroll_h || min.width <= size.width;
if (hide_scroll_v) {
@@ -449,6 +454,10 @@ void ScrollContainer::update_scrollbars() {
scroll.x = h_scroll->get_value();
}
+
+ // Avoid scrollbar overlapping.
+ h_scroll->set_anchor_and_margin(MARGIN_RIGHT, ANCHOR_END, hide_scroll_v ? 0 : -vmin.width);
+ v_scroll->set_anchor_and_margin(MARGIN_BOTTOM, ANCHOR_END, hide_scroll_h ? 0 : -hmin.height);
}
void ScrollContainer::_scroll_moved(float) {
@@ -461,8 +470,12 @@ void ScrollContainer::_scroll_moved(float) {
};
void ScrollContainer::set_enable_h_scroll(bool p_enable) {
+ if (scroll_h == p_enable) {
+ return;
+ }
scroll_h = p_enable;
+ minimum_size_changed();
queue_sort();
}
@@ -472,8 +485,12 @@ bool ScrollContainer::is_h_scroll_enabled() const {
}
void ScrollContainer::set_enable_v_scroll(bool p_enable) {
+ if (scroll_v == p_enable) {
+ return;
+ }
scroll_v = p_enable;
+ minimum_size_changed();
queue_sort();
}
@@ -593,12 +610,11 @@ ScrollContainer::ScrollContainer() {
h_scroll = memnew(HScrollBar);
h_scroll->set_name("_h_scroll");
add_child(h_scroll);
+ h_scroll->connect("value_changed", this, "_scroll_moved");
v_scroll = memnew(VScrollBar);
v_scroll->set_name("_v_scroll");
add_child(v_scroll);
-
- h_scroll->connect("value_changed", this, "_scroll_moved");
v_scroll->connect("value_changed", this, "_scroll_moved");
drag_speed = Vector2();
diff --git a/scene/gui/spin_box.cpp b/scene/gui/spin_box.cpp
index d5da35955c..92377949f8 100644
--- a/scene/gui/spin_box.cpp
+++ b/scene/gui/spin_box.cpp
@@ -259,6 +259,10 @@ bool SpinBox::is_editable() const {
return line_edit->is_editable();
}
+void SpinBox::apply() {
+ _text_entered(line_edit->get_text());
+}
+
void SpinBox::_bind_methods() {
//ClassDB::bind_method(D_METHOD("_value_changed"),&SpinBox::_value_changed);
@@ -272,6 +276,7 @@ void SpinBox::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_prefix"), &SpinBox::get_prefix);
ClassDB::bind_method(D_METHOD("set_editable", "editable"), &SpinBox::set_editable);
ClassDB::bind_method(D_METHOD("is_editable"), &SpinBox::is_editable);
+ ClassDB::bind_method(D_METHOD("apply"), &SpinBox::apply);
ClassDB::bind_method(D_METHOD("_line_edit_focus_exit"), &SpinBox::_line_edit_focus_exit);
ClassDB::bind_method(D_METHOD("get_line_edit"), &SpinBox::get_line_edit);
ClassDB::bind_method(D_METHOD("_line_edit_input"), &SpinBox::_line_edit_input);
diff --git a/scene/gui/spin_box.h b/scene/gui/spin_box.h
index 13ba168ef3..04491c8477 100644
--- a/scene/gui/spin_box.h
+++ b/scene/gui/spin_box.h
@@ -88,6 +88,8 @@ public:
void set_prefix(const String &p_prefix);
String get_prefix() const;
+ void apply();
+
SpinBox();
};
diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp
index d7e469ca26..6de2f0b570 100644
--- a/scene/gui/text_edit.cpp
+++ b/scene/gui/text_edit.cpp
@@ -7070,6 +7070,10 @@ void TextEdit::_bind_methods() {
ClassDB::bind_method(D_METHOD("is_smooth_scroll_enabled"), &TextEdit::is_smooth_scroll_enabled);
ClassDB::bind_method(D_METHOD("set_v_scroll_speed", "speed"), &TextEdit::set_v_scroll_speed);
ClassDB::bind_method(D_METHOD("get_v_scroll_speed"), &TextEdit::get_v_scroll_speed);
+ ClassDB::bind_method(D_METHOD("set_v_scroll", "value"), &TextEdit::set_v_scroll);
+ ClassDB::bind_method(D_METHOD("get_v_scroll"), &TextEdit::get_v_scroll);
+ ClassDB::bind_method(D_METHOD("set_h_scroll", "value"), &TextEdit::set_h_scroll);
+ ClassDB::bind_method(D_METHOD("get_h_scroll"), &TextEdit::get_h_scroll);
ClassDB::bind_method(D_METHOD("add_keyword_color", "keyword", "color"), &TextEdit::add_keyword_color);
ClassDB::bind_method(D_METHOD("has_keyword_color", "keyword"), &TextEdit::has_keyword_color);
@@ -7105,6 +7109,8 @@ void TextEdit::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::REAL, "v_scroll_speed"), "set_v_scroll_speed", "get_v_scroll_speed");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "hiding_enabled"), "set_hiding_enabled", "is_hiding_enabled");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "wrap_enabled"), "set_wrap_enabled", "is_wrap_enabled");
+ ADD_PROPERTY(PropertyInfo(Variant::REAL, "scroll_vertical"), "set_v_scroll", "get_v_scroll");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "scroll_horizontal"), "set_h_scroll", "get_h_scroll");
ADD_GROUP("Minimap", "minimap_");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "minimap_draw"), "draw_minimap", "is_drawing_minimap");
diff --git a/scene/main/node.cpp b/scene/main/node.cpp
index 1e2b7c094e..350959dcc3 100644
--- a/scene/main/node.cpp
+++ b/scene/main/node.cpp
@@ -2680,7 +2680,8 @@ void Node::clear_internal_tree_resource_paths() {
String Node::get_configuration_warning() const {
- if (get_script_instance() && get_script_instance()->has_method("_get_configuration_warning")) {
+ if (get_script_instance() && get_script_instance()->get_script().is_valid() &&
+ get_script_instance()->get_script()->is_tool() && get_script_instance()->has_method("_get_configuration_warning")) {
return get_script_instance()->call("_get_configuration_warning");
}
return String();
diff --git a/scene/main/viewport.cpp b/scene/main/viewport.cpp
index 9e9a25883e..a56903636f 100644
--- a/scene/main/viewport.cpp
+++ b/scene/main/viewport.cpp
@@ -30,6 +30,7 @@
#include "viewport.h"
+#include "core/core_string_names.h"
#include "core/os/input.h"
#include "core/os/os.h"
#include "core/project_settings.h"
@@ -251,6 +252,27 @@ void Viewport::_collision_object_input_event(CollisionObject *p_object, Camera *
physics_last_id = id;
}
+void Viewport::_own_world_changed() {
+ ERR_FAIL_COND(world.is_null());
+ ERR_FAIL_COND(own_world.is_null());
+
+ if (is_inside_tree()) {
+ _propagate_exit_world(this);
+ }
+
+ own_world = world->duplicate();
+
+ if (is_inside_tree()) {
+ _propagate_enter_world(this);
+ }
+
+ if (is_inside_tree()) {
+ VisualServer::get_singleton()->viewport_set_scenario(viewport, find_world()->get_scenario());
+ }
+
+ _update_listener();
+}
+
void Viewport::_notification(int p_what) {
switch (p_what) {
@@ -1105,8 +1127,21 @@ void Viewport::set_world(const Ref<World> &p_world) {
if (is_inside_tree())
_propagate_exit_world(this);
+ if (own_world.is_valid() && world.is_valid()) {
+ world->disconnect(CoreStringNames::get_singleton()->changed, this, "_own_world_changed");
+ }
+
world = p_world;
+ if (own_world.is_valid()) {
+ if (world.is_valid()) {
+ own_world = world->duplicate();
+ world->connect(CoreStringNames::get_singleton()->changed, this, "_own_world_changed");
+ } else {
+ own_world = Ref<World>(memnew(World));
+ }
+ }
+
if (is_inside_tree())
_propagate_enter_world(this);
@@ -2826,10 +2861,19 @@ void Viewport::set_use_own_world(bool p_world) {
if (is_inside_tree())
_propagate_exit_world(this);
- if (!p_world)
+ if (!p_world) {
own_world = Ref<World>();
- else
- own_world = Ref<World>(memnew(World));
+ if (world.is_valid()) {
+ world->disconnect(CoreStringNames::get_singleton()->changed, this, "_own_world_changed");
+ }
+ } else {
+ if (world.is_valid()) {
+ own_world = world->duplicate();
+ world->connect(CoreStringNames::get_singleton()->changed, this, "_own_world_changed");
+ } else {
+ own_world = Ref<World>(memnew(World));
+ }
+ }
if (is_inside_tree())
_propagate_enter_world(this);
@@ -3178,6 +3222,8 @@ void Viewport::_bind_methods() {
ClassDB::bind_method(D_METHOD("_subwindow_visibility_changed"), &Viewport::_subwindow_visibility_changed);
+ ClassDB::bind_method(D_METHOD("_own_world_changed"), &Viewport::_own_world_changed);
+
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "arvr"), "set_use_arvr", "use_arvr");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "size"), "set_size", "get_size");
diff --git a/scene/main/viewport.h b/scene/main/viewport.h
index 396bbc91cd..79b606cda3 100644
--- a/scene/main/viewport.h
+++ b/scene/main/viewport.h
@@ -406,6 +406,8 @@ private:
void _update_canvas_items(Node *p_node);
+ void _own_world_changed();
+
protected:
void _notification(int p_what);
static void _bind_methods();
diff --git a/scene/register_scene_types.cpp b/scene/register_scene_types.cpp
index 21fc9ccf6a..09d4505458 100644
--- a/scene/register_scene_types.cpp
+++ b/scene/register_scene_types.cpp
@@ -372,6 +372,28 @@ void register_scene_types() {
ClassDB::register_class<AnimationPlayer>();
ClassDB::register_class<Tween>();
+ ClassDB::register_class<AnimationTreePlayer>();
+ ClassDB::register_class<AnimationTree>();
+ ClassDB::register_class<AnimationNode>();
+ ClassDB::register_class<AnimationRootNode>();
+ ClassDB::register_class<AnimationNodeBlendTree>();
+ ClassDB::register_class<AnimationNodeBlendSpace1D>();
+ ClassDB::register_class<AnimationNodeBlendSpace2D>();
+ ClassDB::register_class<AnimationNodeStateMachine>();
+ ClassDB::register_class<AnimationNodeStateMachinePlayback>();
+
+ ClassDB::register_class<AnimationNodeStateMachineTransition>();
+ ClassDB::register_class<AnimationNodeOutput>();
+ ClassDB::register_class<AnimationNodeOneShot>();
+ ClassDB::register_class<AnimationNodeAnimation>();
+ ClassDB::register_class<AnimationNodeAdd2>();
+ ClassDB::register_class<AnimationNodeAdd3>();
+ ClassDB::register_class<AnimationNodeBlend2>();
+ ClassDB::register_class<AnimationNodeBlend3>();
+ ClassDB::register_class<AnimationNodeTimeScale>();
+ ClassDB::register_class<AnimationNodeTimeSeek>();
+ ClassDB::register_class<AnimationNodeTransition>();
+
OS::get_singleton()->yield(); //may take time to init
#ifndef _3D_DISABLED
@@ -399,7 +421,6 @@ void register_scene_types() {
ClassDB::register_class<GIProbeData>();
ClassDB::register_class<BakedLightmap>();
ClassDB::register_class<BakedLightmapData>();
- ClassDB::register_class<AnimationTreePlayer>();
ClassDB::register_class<Particles>();
ClassDB::register_class<CPUParticles>();
ClassDB::register_class<Position3D>();
@@ -410,27 +431,6 @@ void register_scene_types() {
ClassDB::register_class<RootMotionView>();
ClassDB::set_class_enabled("RootMotionView", false); //disabled by default, enabled by editor
- ClassDB::register_class<AnimationTree>();
- ClassDB::register_class<AnimationNode>();
- ClassDB::register_class<AnimationRootNode>();
- ClassDB::register_class<AnimationNodeBlendTree>();
- ClassDB::register_class<AnimationNodeBlendSpace1D>();
- ClassDB::register_class<AnimationNodeBlendSpace2D>();
- ClassDB::register_class<AnimationNodeStateMachine>();
- ClassDB::register_class<AnimationNodeStateMachinePlayback>();
-
- ClassDB::register_class<AnimationNodeStateMachineTransition>();
- ClassDB::register_class<AnimationNodeOutput>();
- ClassDB::register_class<AnimationNodeOneShot>();
- ClassDB::register_class<AnimationNodeAnimation>();
- ClassDB::register_class<AnimationNodeAdd2>();
- ClassDB::register_class<AnimationNodeAdd3>();
- ClassDB::register_class<AnimationNodeBlend2>();
- ClassDB::register_class<AnimationNodeBlend3>();
- ClassDB::register_class<AnimationNodeTimeScale>();
- ClassDB::register_class<AnimationNodeTimeSeek>();
- ClassDB::register_class<AnimationNodeTransition>();
-
OS::get_singleton()->yield(); //may take time to init
ClassDB::register_virtual_class<CollisionObject>();
diff --git a/scene/resources/default_theme/default_theme.cpp b/scene/resources/default_theme/default_theme.cpp
index 67351f07d2..cc76df62e5 100644
--- a/scene/resources/default_theme/default_theme.cpp
+++ b/scene/resources/default_theme/default_theme.cpp
@@ -851,6 +851,8 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const
theme->set_stylebox("bg", "GraphEdit", make_stylebox(tree_bg_png, 4, 4, 4, 5));
theme->set_color("grid_minor", "GraphEdit", Color(1, 1, 1, 0.05));
theme->set_color("grid_major", "GraphEdit", Color(1, 1, 1, 0.2));
+ theme->set_color("selection_fill", "GraphEdit", Color(1, 1, 1, 0.3));
+ theme->set_color("selection_stroke", "GraphEdit", Color(1, 1, 1, 0.8));
theme->set_color("activity", "GraphEdit", Color(1, 1, 1));
theme->set_constant("bezier_len_pos", "GraphEdit", 80 * scale);
theme->set_constant("bezier_len_neg", "GraphEdit", 160 * scale);
diff --git a/scene/resources/dynamic_font.cpp b/scene/resources/dynamic_font.cpp
index 42fec3a0a7..8b619345d6 100644
--- a/scene/resources/dynamic_font.cpp
+++ b/scene/resources/dynamic_font.cpp
@@ -195,13 +195,13 @@ Error DynamicFontAtSize::_load() {
if (FT_HAS_COLOR(face) && face->num_fixed_sizes > 0) {
int best_match = 0;
int diff = ABS(id.size - ((int64_t)face->available_sizes[0].width));
- scale_color_font = float(id.size) / face->available_sizes[0].width;
+ scale_color_font = float(id.size * oversampling) / face->available_sizes[0].width;
for (int i = 1; i < face->num_fixed_sizes; i++) {
int ndiff = ABS(id.size - ((int64_t)face->available_sizes[i].width));
if (ndiff < diff) {
best_match = i;
diff = ndiff;
- scale_color_font = float(id.size) / face->available_sizes[i].width;
+ scale_color_font = float(id.size * oversampling) / face->available_sizes[i].width;
}
}
FT_Select_Size(face, best_match);
@@ -299,7 +299,7 @@ void DynamicFontAtSize::set_texture_flags(uint32_t p_flags) {
}
}
-float DynamicFontAtSize::draw_char(RID p_canvas_item, const Point2 &p_pos, CharType p_char, CharType p_next, const Color &p_modulate, const Vector<Ref<DynamicFontAtSize> > &p_fallbacks, bool p_advance_only) const {
+float DynamicFontAtSize::draw_char(RID p_canvas_item, const Point2 &p_pos, CharType p_char, CharType p_next, const Color &p_modulate, const Vector<Ref<DynamicFontAtSize> > &p_fallbacks, bool p_advance_only, bool p_outline) const {
if (!valid)
return 0;
@@ -314,6 +314,20 @@ float DynamicFontAtSize::draw_char(RID p_canvas_item, const Point2 &p_pos, CharT
float advance = 0.0;
+ // use normal character size if there's no outline character
+ if (p_outline && !ch->found) {
+ FT_GlyphSlot slot = face->glyph;
+ int error = FT_Load_Char(face, p_char, FT_HAS_COLOR(face) ? FT_LOAD_COLOR : FT_LOAD_DEFAULT);
+ if (!error) {
+ error = FT_Render_Glyph(face->glyph, FT_RENDER_MODE_NORMAL);
+ if (!error) {
+ Character character = Character::not_found();
+ character = const_cast<DynamicFontAtSize *>(this)->_bitmap_to_character(slot->bitmap, slot->bitmap_top, slot->bitmap_left, slot->advance.x / 64.0);
+ advance = character.advance;
+ }
+ }
+ }
+
if (ch->found) {
ERR_FAIL_COND_V(ch->texture_idx < -1 || ch->texture_idx >= font->textures.size(), 0);
@@ -875,7 +889,7 @@ float DynamicFont::draw_char(RID p_canvas_item, const Point2 &p_pos, CharType p_
// If requested outline draw, but no outline is present, simply return advance without drawing anything
bool advance_only = p_outline && outline_cache_id.outline_size == 0;
- return font_at_size->draw_char(p_canvas_item, p_pos, p_char, p_next, color, fallbacks, advance_only) + spacing_char;
+ return font_at_size->draw_char(p_canvas_item, p_pos, p_char, p_next, color, fallbacks, advance_only, p_outline) + spacing_char;
}
void DynamicFont::set_fallback(int p_idx, const Ref<DynamicFontData> &p_data) {
diff --git a/scene/resources/dynamic_font.h b/scene/resources/dynamic_font.h
index ece150c4ce..2dafd3ce4f 100644
--- a/scene/resources/dynamic_font.h
+++ b/scene/resources/dynamic_font.h
@@ -192,7 +192,7 @@ public:
Size2 get_char_size(CharType p_char, CharType p_next, const Vector<Ref<DynamicFontAtSize> > &p_fallbacks) const;
- float draw_char(RID p_canvas_item, const Point2 &p_pos, CharType p_char, CharType p_next, const Color &p_modulate, const Vector<Ref<DynamicFontAtSize> > &p_fallbacks, bool p_advance_only = false) const;
+ float draw_char(RID p_canvas_item, const Point2 &p_pos, CharType p_char, CharType p_next, const Color &p_modulate, const Vector<Ref<DynamicFontAtSize> > &p_fallbacks, bool p_advance_only = false, bool p_outline = false) const;
void set_texture_flags(uint32_t p_flags);
void update_oversampling();
diff --git a/scene/resources/mesh.cpp b/scene/resources/mesh.cpp
index 13721191c0..0599920303 100644
--- a/scene/resources/mesh.cpp
+++ b/scene/resources/mesh.cpp
@@ -75,6 +75,7 @@ Ref<TriangleMesh> Mesh::generate_triangle_mesh() const {
continue;
Array a = surface_get_arrays(i);
+ ERR_FAIL_COND_V(a.empty(), Ref<TriangleMesh>());
int vc = surface_get_array_len(i);
PoolVector<Vector3> vertices = a[ARRAY_VERTEX];
@@ -234,6 +235,7 @@ Ref<Shape> Mesh::create_convex_shape() const {
for (int i = 0; i < get_surface_count(); i++) {
Array a = surface_get_arrays(i);
+ ERR_FAIL_COND_V(a.empty(), Ref<ConvexPolygonShape>());
PoolVector<Vector3> v = a[ARRAY_VERTEX];
vertices.append_array(v);
}
@@ -273,6 +275,7 @@ Ref<Mesh> Mesh::create_outline(float p_margin) const {
continue;
Array a = surface_get_arrays(i);
+ ERR_FAIL_COND_V(a.empty(), Ref<ArrayMesh>());
if (i == 0) {
arrays = a;
@@ -378,6 +381,7 @@ Ref<Mesh> Mesh::create_outline(float p_margin) const {
PoolVector<Vector3>::Write r = vertices.write();
if (indices.size()) {
+ ERR_FAIL_COND_V(indices.size() % 3 != 0, Ref<ArrayMesh>());
vc = indices.size();
ir = indices.write();
has_indices = true;
diff --git a/scene/resources/packed_scene.cpp b/scene/resources/packed_scene.cpp
index 5a2cd9a1c2..3e7d350eec 100644
--- a/scene/resources/packed_scene.cpp
+++ b/scene/resources/packed_scene.cpp
@@ -39,7 +39,7 @@
#include "scene/gui/control.h"
#include "scene/main/instance_placeholder.h"
-#define PACK_VERSION 2
+#define PACKED_SCENE_VERSION 2
bool SceneState::can_instance() const {
@@ -1095,7 +1095,15 @@ void SceneState::set_bundled_scene(const Dictionary &p_dictionary) {
if (p_dictionary.has("version"))
version = p_dictionary["version"];
- ERR_FAIL_COND_MSG(version > PACK_VERSION, "Save format version too new.");
+ ERR_FAIL_COND_MSG(version > PACKED_SCENE_VERSION, "Save format version too new.");
+
+ const int node_count = p_dictionary["node_count"];
+ const PoolVector<int> snodes = p_dictionary["nodes"];
+ ERR_FAIL_COND(snodes.size() < node_count);
+
+ const int conn_count = p_dictionary["conn_count"];
+ const PoolVector<int> sconns = p_dictionary["conns"];
+ ERR_FAIL_COND(sconns.size() < conn_count);
PoolVector<String> snames = p_dictionary["names"];
if (snames.size()) {
@@ -1121,13 +1129,11 @@ void SceneState::set_bundled_scene(const Dictionary &p_dictionary) {
variants.clear();
}
- nodes.resize(p_dictionary["node_count"]);
- int nc = nodes.size();
- if (nc) {
- PoolVector<int> snodes = p_dictionary["nodes"];
+ nodes.resize(node_count);
+ if (node_count) {
PoolVector<int>::Read r = snodes.read();
int idx = 0;
- for (int i = 0; i < nc; i++) {
+ for (int i = 0; i < node_count; i++) {
NodeData &nd = nodes.write[i];
nd.parent = r[idx++];
nd.owner = r[idx++];
@@ -1151,15 +1157,11 @@ void SceneState::set_bundled_scene(const Dictionary &p_dictionary) {
}
}
- connections.resize(p_dictionary["conn_count"]);
- int cc = connections.size();
-
- if (cc) {
-
- PoolVector<int> sconns = p_dictionary["conns"];
+ connections.resize(conn_count);
+ if (conn_count) {
PoolVector<int>::Read r = sconns.read();
int idx = 0;
- for (int i = 0; i < cc; i++) {
+ for (int i = 0; i < conn_count; i++) {
ConnectionData &cd = connections.write[i];
cd.from = r[idx++];
cd.to = r[idx++];
@@ -1283,9 +1285,7 @@ Dictionary SceneState::get_bundled_scene() const {
d["base_scene"] = base_scene_idx;
}
- d["version"] = PACK_VERSION;
-
- //d["path"]=path;
+ d["version"] = PACKED_SCENE_VERSION;
return d;
}
diff --git a/scene/resources/particles_material.cpp b/scene/resources/particles_material.cpp
index a058f42cb2..412b5c259c 100644
--- a/scene/resources/particles_material.cpp
+++ b/scene/resources/particles_material.cpp
@@ -198,6 +198,9 @@ void ParticlesMaterial::_update_shader() {
code += "uniform sampler2D emission_texture_color : hint_white;\n";
}
} break;
+ case EMISSION_SHAPE_MAX: { // Max value for validity check.
+ break;
+ }
}
code += "uniform vec4 color_value : hint_color;\n";
@@ -283,7 +286,7 @@ void ParticlesMaterial::_update_shader() {
code += " float degree_to_rad = pi / 180.0;\n";
code += "\n";
- if (emission_shape >= EMISSION_SHAPE_POINTS) {
+ if (emission_shape == EMISSION_SHAPE_POINTS || emission_shape == EMISSION_SHAPE_DIRECTED_POINTS) {
code += " int point = min(emission_texture_point_count - 1, int(rand_from_seed(alt_seed) * float(emission_texture_point_count)));\n";
code += " ivec2 emission_tex_size = textureSize(emission_texture_points, 0);\n";
code += " ivec2 emission_tex_ofs = ivec2(point % emission_tex_size.x, point / emission_tex_size.x);\n";
@@ -368,6 +371,9 @@ void ParticlesMaterial::_update_shader() {
}
}
} break;
+ case EMISSION_SHAPE_MAX: { // Max value for validity check.
+ break;
+ }
}
code += " VELOCITY = (EMISSION_TRANSFORM * vec4(VELOCITY, 0.0)).xyz;\n";
code += " TRANSFORM = EMISSION_TRANSFORM * TRANSFORM;\n";
@@ -515,7 +521,7 @@ void ParticlesMaterial::_update_shader() {
} else {
code += " COLOR = hue_rot_mat * color_value;\n";
}
- if (emission_color_texture.is_valid() && emission_shape >= EMISSION_SHAPE_POINTS) {
+ if (emission_color_texture.is_valid() && (emission_shape == EMISSION_SHAPE_POINTS || emission_shape == EMISSION_SHAPE_DIRECTED_POINTS)) {
code += " COLOR *= texelFetch(emission_texture_color, emission_tex_ofs, 0);\n";
}
if (trail_color_modifier.is_valid()) {
@@ -894,7 +900,7 @@ bool ParticlesMaterial::get_flag(Flags p_flag) const {
}
void ParticlesMaterial::set_emission_shape(EmissionShape p_shape) {
-
+ ERR_FAIL_INDEX(p_shape, EMISSION_SHAPE_MAX);
emission_shape = p_shape;
_change_notify();
_queue_shader_change();
@@ -1242,6 +1248,7 @@ void ParticlesMaterial::_bind_methods() {
BIND_ENUM_CONSTANT(EMISSION_SHAPE_BOX);
BIND_ENUM_CONSTANT(EMISSION_SHAPE_POINTS);
BIND_ENUM_CONSTANT(EMISSION_SHAPE_DIRECTED_POINTS);
+ BIND_ENUM_CONSTANT(EMISSION_SHAPE_MAX);
}
ParticlesMaterial::ParticlesMaterial() :
diff --git a/scene/resources/particles_material.h b/scene/resources/particles_material.h
index 643c2cb10e..cc860b3812 100644
--- a/scene/resources/particles_material.h
+++ b/scene/resources/particles_material.h
@@ -69,6 +69,7 @@ public:
EMISSION_SHAPE_BOX,
EMISSION_SHAPE_POINTS,
EMISSION_SHAPE_DIRECTED_POINTS,
+ EMISSION_SHAPE_MAX
};
private:
diff --git a/scene/resources/style_box.cpp b/scene/resources/style_box.cpp
index c59fa8cab8..9408d1aa71 100644
--- a/scene/resources/style_box.cpp
+++ b/scene/resources/style_box.cpp
@@ -719,6 +719,7 @@ void StyleBoxFlat::draw(RID p_canvas_item, const Rect2 &p_rect) const {
bool rounded_corners = (corner_radius[0] > 0) || (corner_radius[1] > 0) || (corner_radius[2] > 0) || (corner_radius[3] > 0);
bool aa_on = rounded_corners && anti_aliased;
+ float aa_size_grow = 0.5 * ((float)aa_size + 1.0);
bool blend_on = blend_border && draw_border;
@@ -744,7 +745,6 @@ void StyleBoxFlat::draw(RID p_canvas_item, const Rect2 &p_rect) const {
Rect2 border_style_rect = style_rect;
if (aa_on) {
- float aa_size_grow = 0.5 * ((aa_size + 1) / 2);
for (int i = 0; i < 4; i++) {
if (border_width[i] > 0) {
border_style_rect = border_style_rect.grow_margin((Margin)i, -aa_size_grow);
@@ -789,7 +789,6 @@ void StyleBoxFlat::draw(RID p_canvas_item, const Rect2 &p_rect) const {
}
if (aa_on) {
- float aa_size_grow = 0.5 * ((aa_size + 1) / 2);
int aa_border_width[4];
int aa_fill_width[4];
if (draw_border) {
@@ -804,6 +803,7 @@ void StyleBoxFlat::draw(RID p_canvas_item, const Rect2 &p_rect) const {
}
} else {
for (int i = 0; i < 4; i++) {
+ aa_border_width[i] = 0;
aa_fill_width[i] = aa_size_grow;
}
}
@@ -844,7 +844,7 @@ void StyleBoxFlat::draw(RID p_canvas_item, const Rect2 &p_rect) const {
}
//COMPUTE UV COORDINATES
- Rect2 uv_rect = style_rect.grow(aa_on ? aa_size : 0);
+ Rect2 uv_rect = style_rect.grow(aa_on ? aa_size_grow : 0);
uvs.resize(verts.size());
for (int i = 0; i < verts.size(); i++) {
uvs.write[i].x = (verts[i].x - uv_rect.position.x) / uv_rect.size.width;
diff --git a/scene/resources/texture.cpp b/scene/resources/texture.cpp
index dc2b708ae7..4d23f0eb41 100644
--- a/scene/resources/texture.cpp
+++ b/scene/resources/texture.cpp
@@ -2271,6 +2271,7 @@ void TextureLayered::create(uint32_t p_width, uint32_t p_height, uint32_t p_dept
void TextureLayered::set_layer_data(const Ref<Image> &p_image, int p_layer) {
ERR_FAIL_COND(!texture.is_valid());
+ ERR_FAIL_COND(!p_image.is_valid());
VS::get_singleton()->texture_set_data(texture, p_image, p_layer);
}
@@ -2282,6 +2283,7 @@ Ref<Image> TextureLayered::get_layer_data(int p_layer) const {
void TextureLayered::set_data_partial(const Ref<Image> &p_image, int p_x_ofs, int p_y_ofs, int p_z, int p_mipmap) {
ERR_FAIL_COND(!texture.is_valid());
+ ERR_FAIL_COND(!p_image.is_valid());
VS::get_singleton()->texture_set_data_partial(texture, p_image, 0, 0, p_image->get_width(), p_image->get_height(), p_x_ofs, p_y_ofs, p_mipmap, p_z);
}
diff --git a/scene/resources/visual_shader_nodes.cpp b/scene/resources/visual_shader_nodes.cpp
index 0035a138d7..f46fba3b5b 100644
--- a/scene/resources/visual_shader_nodes.cpp
+++ b/scene/resources/visual_shader_nodes.cpp
@@ -3685,12 +3685,33 @@ String VisualShaderNodeFresnel::get_output_port_name(int p_port) const {
}
String VisualShaderNodeFresnel::generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview) const {
- return "\t" + p_output_vars[0] + " = " + p_input_vars[2] + " ? (pow(clamp(dot(" + p_input_vars[0] + ", " + p_input_vars[1] + "), 0.0, 1.0), " + p_input_vars[3] + ")) : (pow(1.0 - clamp(dot(" + p_input_vars[0] + ", " + p_input_vars[1] + "), 0.0, 1.0), " + p_input_vars[3] + "));";
+
+ String normal;
+ String view;
+ if (p_input_vars[0] == String()) {
+ normal = "NORMAL";
+ } else {
+ normal = p_input_vars[0];
+ }
+ if (p_input_vars[1] == String()) {
+ view = "VIEW";
+ } else {
+ view = p_input_vars[1];
+ }
+
+ return "\t" + p_output_vars[0] + " = " + p_input_vars[2] + " ? (pow(clamp(dot(" + normal + ", " + view + "), 0.0, 1.0), " + p_input_vars[3] + ")) : (pow(1.0 - clamp(dot(" + normal + ", " + view + "), 0.0, 1.0), " + p_input_vars[3] + "));";
+}
+
+String VisualShaderNodeFresnel::get_input_port_default_hint(int p_port) const {
+ if (p_port == 0) {
+ return "default";
+ } else if (p_port == 1) {
+ return "default";
+ }
+ return "";
}
VisualShaderNodeFresnel::VisualShaderNodeFresnel() {
- set_input_port_default_value(0, Vector3(0.0, 0.0, 0.0));
- set_input_port_default_value(1, Vector3(0.0, 0.0, 0.0));
set_input_port_default_value(2, false);
set_input_port_default_value(3, 1.0);
}
diff --git a/scene/resources/visual_shader_nodes.h b/scene/resources/visual_shader_nodes.h
index 99b4c01d53..0f428088e0 100644
--- a/scene/resources/visual_shader_nodes.h
+++ b/scene/resources/visual_shader_nodes.h
@@ -1579,6 +1579,7 @@ public:
virtual PortType get_output_port_type(int p_port) const;
virtual String get_output_port_name(int p_port) const;
+ virtual String get_input_port_default_hint(int p_port) const;
virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const;
VisualShaderNodeFresnel();
diff --git a/scene/resources/world.cpp b/scene/resources/world.cpp
index b498acd707..1099852098 100644
--- a/scene/resources/world.cpp
+++ b/scene/resources/world.cpp
@@ -268,12 +268,17 @@ RID World::get_scenario() const {
}
void World::set_environment(const Ref<Environment> &p_environment) {
+ if (environment == p_environment) {
+ return;
+ }
environment = p_environment;
if (environment.is_valid())
VS::get_singleton()->scenario_set_environment(scenario, environment->get_rid());
else
VS::get_singleton()->scenario_set_environment(scenario, RID());
+
+ emit_changed();
}
Ref<Environment> World::get_environment() const {
@@ -282,12 +287,17 @@ Ref<Environment> World::get_environment() const {
}
void World::set_fallback_environment(const Ref<Environment> &p_environment) {
+ if (fallback_environment == p_environment) {
+ return;
+ }
fallback_environment = p_environment;
if (fallback_environment.is_valid())
VS::get_singleton()->scenario_set_fallback_environment(scenario, p_environment->get_rid());
else
VS::get_singleton()->scenario_set_fallback_environment(scenario, RID());
+
+ emit_changed();
}
Ref<Environment> World::get_fallback_environment() const {
diff --git a/servers/physics/area_sw.cpp b/servers/physics/area_sw.cpp
index f9f7f67a1e..398849edb8 100644
--- a/servers/physics/area_sw.cpp
+++ b/servers/physics/area_sw.cpp
@@ -46,6 +46,9 @@ AreaSW::BodyKey::BodyKey(AreaSW *p_body, uint32_t p_body_shape, uint32_t p_area_
}
void AreaSW::_shapes_changed() {
+
+ if (!moved_list.in_list() && get_space())
+ get_space()->area_add_to_moved_list(&moved_list);
}
void AreaSW::set_transform(const Transform &p_transform) {
diff --git a/servers/physics_2d/area_2d_sw.cpp b/servers/physics_2d/area_2d_sw.cpp
index 110e94d22e..6f09041af8 100644
--- a/servers/physics_2d/area_2d_sw.cpp
+++ b/servers/physics_2d/area_2d_sw.cpp
@@ -46,6 +46,9 @@ Area2DSW::BodyKey::BodyKey(Area2DSW *p_body, uint32_t p_body_shape, uint32_t p_a
}
void Area2DSW::_shapes_changed() {
+
+ if (!moved_list.in_list() && get_space())
+ get_space()->area_add_to_moved_list(&moved_list);
}
void Area2DSW::set_transform(const Transform2D &p_transform) {
diff --git a/servers/visual/rasterizer.h b/servers/visual/rasterizer.h
index 74741a946c..0008b809b7 100644
--- a/servers/visual/rasterizer.h
+++ b/servers/visual/rasterizer.h
@@ -588,6 +588,8 @@ public:
virtual int get_captured_render_info(VS::RenderInfo p_info) = 0;
virtual int get_render_info(VS::RenderInfo p_info) = 0;
+ virtual String get_video_adapter_name() const = 0;
+ virtual String get_video_adapter_vendor() const = 0;
static RasterizerStorage *base_singleton;
RasterizerStorage();
diff --git a/servers/visual/shader_language.cpp b/servers/visual/shader_language.cpp
index 45084b60a2..2b61d72f6a 100644
--- a/servers/visual/shader_language.cpp
+++ b/servers/visual/shader_language.cpp
@@ -571,8 +571,10 @@ ShaderLanguage::Token ShaderLanguage::_get_token() {
CharType last_char = str[str.length() - 1];
if (hexa_found) {
- //hex integers eg."0xFF" or "0x12AB", etc - NOT supported yet
- return _make_token(TK_ERROR, "Invalid (hexadecimal) numeric constant - Not supported");
+ //integer(hex)
+ if (str.size() > 11 || !str.is_valid_hex_number(true)) { // > 0xFFFFFFFF
+ return _make_token(TK_ERROR, "Invalid (hexadecimal) numeric constant");
+ }
} else if (period_found || exponent_found || float_suffix_found) {
//floats
if (period_found) {
@@ -621,7 +623,11 @@ ShaderLanguage::Token ShaderLanguage::_get_token() {
else
tk.type = TK_INT_CONSTANT;
- tk.constant = str.to_double(); //won't work with hex
+ if (hexa_found) {
+ tk.constant = (double)str.hex_to_int64(true);
+ } else {
+ tk.constant = str.to_double();
+ }
tk.line = tk_line;
return tk;
@@ -2054,7 +2060,7 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = {
//sub-functions
//array
- { "length", TYPE_INT, { TYPE_VOID }, TAG_ARRAY, false },
+ { "length", TYPE_INT, { TYPE_VOID }, TAG_ARRAY, true },
{ NULL, TYPE_VOID, { TYPE_VOID }, TAG_GLOBAL, false }
@@ -3882,6 +3888,11 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const Map<StringName, Bui
if (tk.type == TK_BRACKET_OPEN) {
bool unknown_size = false;
+ if (VisualServer::get_singleton()->is_low_end() && is_const) {
+ _set_error("Local const arrays are supported only on high-end platform!");
+ return ERR_PARSE_ERROR;
+ }
+
ArrayDeclarationNode *node = alloc_node<ArrayDeclarationNode>();
node->datatype = type;
node->precision = precision;
@@ -3917,6 +3928,12 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const Map<StringName, Bui
tk = _get_token();
if (tk.type == TK_OP_ASSIGN) {
+
+ if (VisualServer::get_singleton()->is_low_end()) {
+ _set_error("Array initialization is supported only on high-end platform!");
+ return ERR_PARSE_ERROR;
+ }
+
tk = _get_token();
if (tk.type != TK_CURLY_BRACKET_OPEN) {
@@ -4536,8 +4553,13 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const Map<StringName, Bui
}
p_block->statements.push_back(flow);
- if (p_block->block_type == BlockNode::BLOCK_TYPE_CASE || p_block->block_type == BlockNode::BLOCK_TYPE_DEFAULT) {
- return OK;
+
+ BlockNode *block = p_block;
+ while (block) {
+ if (block->block_type == BlockNode::BLOCK_TYPE_CASE || block->block_type == BlockNode::BLOCK_TYPE_DEFAULT) {
+ return OK;
+ }
+ block = block->parent_block;
}
} else if (tk.type == TK_CF_DISCARD) {
@@ -4585,8 +4607,13 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const Map<StringName, Bui
}
p_block->statements.push_back(flow);
- if (p_block->block_type == BlockNode::BLOCK_TYPE_CASE || p_block->block_type == BlockNode::BLOCK_TYPE_DEFAULT) {
- return OK;
+
+ BlockNode *block = p_block;
+ while (block) {
+ if (block->block_type == BlockNode::BLOCK_TYPE_CASE || block->block_type == BlockNode::BLOCK_TYPE_DEFAULT) {
+ return OK;
+ }
+ block = block->parent_block;
}
} else if (tk.type == TK_CF_CONTINUE) {
diff --git a/servers/visual/visual_server_raster.cpp b/servers/visual/visual_server_raster.cpp
index 4d680667cb..23736b5e63 100644
--- a/servers/visual/visual_server_raster.cpp
+++ b/servers/visual/visual_server_raster.cpp
@@ -153,6 +153,16 @@ int VisualServerRaster::get_render_info(RenderInfo p_info) {
return VSG::storage->get_render_info(p_info);
}
+String VisualServerRaster::get_video_adapter_name() const {
+
+ return VSG::storage->get_video_adapter_name();
+}
+
+String VisualServerRaster::get_video_adapter_vendor() const {
+
+ return VSG::storage->get_video_adapter_vendor();
+}
+
/* TESTING */
void VisualServerRaster::set_boot_image(const Ref<Image> &p_image, const Color &p_color, bool p_scale, bool p_use_filter) {
diff --git a/servers/visual/visual_server_raster.h b/servers/visual/visual_server_raster.h
index 54c46b1812..1a1e86833e 100644
--- a/servers/visual/visual_server_raster.h
+++ b/servers/visual/visual_server_raster.h
@@ -680,6 +680,8 @@ public:
/* 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 RID get_test_cube();
diff --git a/servers/visual/visual_server_wrap_mt.h b/servers/visual/visual_server_wrap_mt.h
index f5875f4fad..b8f433d006 100644
--- a/servers/visual/visual_server_wrap_mt.h
+++ b/servers/visual/visual_server_wrap_mt.h
@@ -101,7 +101,7 @@ public:
FUNC2(texture_set_path, RID, const String &)
FUNC1RC(String, texture_get_path, RID)
FUNC1(texture_set_shrink_all_x2_on_set_data, bool)
- FUNC1(texture_debug_usage, List<TextureInfo> *)
+ FUNC1S(texture_debug_usage, List<TextureInfo> *)
FUNC1(textures_keep_original, bool)
@@ -602,6 +602,14 @@ public:
return visual_server->get_render_info(p_info);
}
+ virtual String get_video_adapter_name() const {
+ return visual_server->get_video_adapter_name();
+ }
+
+ virtual String get_video_adapter_vendor() const {
+ return visual_server->get_video_adapter_vendor();
+ }
+
FUNC4(set_boot_image, const Ref<Image> &, const Color &, bool, bool)
FUNC1(set_default_clear_color, const Color &)
diff --git a/servers/visual_server.cpp b/servers/visual_server.cpp
index 1f72848b15..b9b492e758 100644
--- a/servers/visual_server.cpp
+++ b/servers/visual_server.cpp
@@ -2032,6 +2032,8 @@ void VisualServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("init"), &VisualServer::init);
ClassDB::bind_method(D_METHOD("finish"), &VisualServer::finish);
ClassDB::bind_method(D_METHOD("get_render_info", "info"), &VisualServer::get_render_info);
+ ClassDB::bind_method(D_METHOD("get_video_adapter_name"), &VisualServer::get_video_adapter_name);
+ ClassDB::bind_method(D_METHOD("get_video_adapter_vendor"), &VisualServer::get_video_adapter_vendor);
#ifndef _3D_DISABLED
ClassDB::bind_method(D_METHOD("make_sphere_mesh", "latitudes", "longitudes", "radius"), &VisualServer::make_sphere_mesh);
diff --git a/servers/visual_server.h b/servers/visual_server.h
index 9aeee731b3..6f0659357c 100644
--- a/servers/visual_server.h
+++ b/servers/visual_server.h
@@ -335,12 +335,14 @@ public:
MULTIMESH_COLOR_NONE,
MULTIMESH_COLOR_8BIT,
MULTIMESH_COLOR_FLOAT,
+ MULTIMESH_COLOR_MAX,
};
enum MultimeshCustomDataFormat {
MULTIMESH_CUSTOM_DATA_NONE,
MULTIMESH_CUSTOM_DATA_8BIT,
MULTIMESH_CUSTOM_DATA_FLOAT,
+ MULTIMESH_CUSTOM_DATA_MAX,
};
virtual void multimesh_allocate(RID p_multimesh, int p_instances, MultimeshTransformFormat p_transform_format, MultimeshColorFormat p_color_format, MultimeshCustomDataFormat p_data_format = MULTIMESH_CUSTOM_DATA_NONE) = 0;
@@ -1017,6 +1019,8 @@ public:
};
virtual int get_render_info(RenderInfo p_info) = 0;
+ virtual String get_video_adapter_name() const = 0;
+ virtual String get_video_adapter_vendor() const = 0;
/* Materials for 2D on 3D */
diff --git a/thirdparty/README.md b/thirdparty/README.md
index 2ab0aedf1c..b29f4bd5e8 100644
--- a/thirdparty/README.md
+++ b/thirdparty/README.md
@@ -11,7 +11,7 @@
## bullet
- Upstream: https://github.com/bulletphysics/bullet3
-- Version: git (5ec8339, 2019)
+- Version: 2.89
- License: zlib
Files extracted from upstream source:
@@ -46,7 +46,7 @@ Files extracted from upstream source:
## enet
- Upstream: http://enet.bespin.org
-- Version: 1.3.13
+- Version: 1.3.14 (0eaf48e, 2019)
- License: MIT
Files extracted from upstream source:
@@ -57,12 +57,14 @@ Files extracted from upstream source:
Important: enet.h, host.c, protocol.c have been slightly modified
to be usable by godot socket implementation and allow IPv6.
+Apply the patch in the `patches/` folder when syncing on newer upstream
+commits.
+
Two files (godot.cpp and enet/godot.h) have been added to provide
enet socket implementation using Godot classes.
+
It is still possible to build against a system wide ENet but doing so
will limit it's functionality to IPv4 only.
-Check the diff of enet.h, protocol.c, and host.c with the 1.3.13
-tarball before the next update.
## etc2comp
@@ -235,7 +237,7 @@ from the Android NDK r18.
## libwebp
- Upstream: https://chromium.googlesource.com/webm/libwebp/
-- Version: 1.0.3
+- Version: 1.1.0
- License: BSD-3-Clause
Files extracted from upstream source:
@@ -496,15 +498,13 @@ File extracted from upstream release tarball:
## xatlas
- Upstream: https://github.com/jpcy/xatlas
-- Version: git (b4b5426, 2019)
+- Version: git (e12ea82, 2019)
- License: MIT
Files extracted from upstream source:
- `xatlas.{cpp,h}`
-
-Note: License is marked as Public Domain in the files, but it was
-later clarified upstream to MIT license.
+- `LICENSE`
## zlib
diff --git a/thirdparty/bullet/Bullet3Common/b3Logging.h b/thirdparty/bullet/Bullet3Common/b3Logging.h
index 9c92b12ebb..f61149de77 100644
--- a/thirdparty/bullet/Bullet3Common/b3Logging.h
+++ b/thirdparty/bullet/Bullet3Common/b3Logging.h
@@ -14,20 +14,8 @@ extern "C"
//#define b3Printf b3OutputPrintfVarArgsInternal
//#define b3Printf(...) printf(__VA_ARGS__)
//#define b3Printf(...)
-
-#define b3Warning(...) \
- do \
- { \
- b3OutputWarningMessageVarArgsInternal("b3Warning[%s,%d]:\n", __FILE__, __LINE__); \
- b3OutputWarningMessageVarArgsInternal(__VA_ARGS__); \
- } while (0)
-#define b3Error(...) \
- do \
- { \
- b3OutputErrorMessageVarArgsInternal("b3Error[%s,%d]:\n", __FILE__, __LINE__); \
- b3OutputErrorMessageVarArgsInternal(__VA_ARGS__); \
- } while (0)
-
+#define b3Warning(...) do{ b3OutputWarningMessageVarArgsInternal("b3Warning[%s,%d]:\n", __FILE__, __LINE__);b3OutputWarningMessageVarArgsInternal(__VA_ARGS__);} while (0)
+#define b3Error(...)do {b3OutputErrorMessageVarArgsInternal("b3Error[%s,%d]:\n", __FILE__, __LINE__);b3OutputErrorMessageVarArgsInternal(__VA_ARGS__);} while (0)
#ifndef B3_NO_PROFILE
void b3EnterProfileZone(const char* name);
diff --git a/thirdparty/bullet/Bullet3Common/b3Scalar.h b/thirdparty/bullet/Bullet3Common/b3Scalar.h
index 0db5eb6f4f..eeb70ed632 100644
--- a/thirdparty/bullet/Bullet3Common/b3Scalar.h
+++ b/thirdparty/bullet/Bullet3Common/b3Scalar.h
@@ -40,8 +40,12 @@ inline int b3GetVersion()
#ifdef _WIN32
-#if defined(__MINGW32__) || defined(__CYGWIN__) || (defined(_MSC_VER) && _MSC_VER < 1300)
-
+#if defined(__GNUC__) // it should handle both MINGW and CYGWIN
+#define B3_FORCE_INLINE __inline__ __attribute__((always_inline))
+#define B3_ATTRIBUTE_ALIGNED16(a) a __attribute__((aligned(16)))
+#define B3_ATTRIBUTE_ALIGNED64(a) a __attribute__((aligned(64)))
+#define B3_ATTRIBUTE_ALIGNED128(a) a __attribute__((aligned(128)))
+#elif ( defined(_MSC_VER) && _MSC_VER < 1300 )
#define B3_FORCE_INLINE inline
#define B3_ATTRIBUTE_ALIGNED16(a) a
#define B3_ATTRIBUTE_ALIGNED64(a) a
@@ -67,7 +71,17 @@ inline int b3GetVersion()
#if (defined(_WIN32) && (_MSC_VER) && _MSC_VER >= 1400) && (!defined(B3_USE_DOUBLE_PRECISION))
#if (defined(_M_IX86) || defined(_M_X64))
+
+
+#ifdef __clang__
+//#define B3_NO_SIMD_OPERATOR_OVERLOADS
+#define B3_DISABLE_SSE
+#endif //__clang__
+
+#ifndef B3_DISABLE_SSE
#define B3_USE_SSE
+#endif //B3_DISABLE_SSE
+
#ifdef B3_USE_SSE
//B3_USE_SSE_IN_API is disabled under Windows by default, because
//it makes it harder to integrate Bullet into your application under Windows
@@ -88,17 +102,7 @@ inline int b3GetVersion()
#ifdef B3_DEBUG
#ifdef _MSC_VER
#include <stdio.h>
-#define b3Assert(x) \
- { \
- if (!(x)) \
- { \
- b3Error( \
- "Assert "__FILE__ \
- ":%u (" #x ")\n", \
- __LINE__); \
- __debugbreak(); \
- } \
- }
+#define b3Assert(x) { if(!(x)){b3Error("Assert " __FILE__ ":%u (%s)\n", __LINE__, #x);__debugbreak(); }}
#else //_MSC_VER
#include <assert.h>
#define b3Assert assert
@@ -293,7 +297,7 @@ static int b3NanMask = 0x7F800001;
static int b3InfinityMask = 0x7F800000;
#define B3_INFINITY_MASK (*(float *)&b3InfinityMask)
#endif
-
+#ifndef B3_NO_SIMD_OPERATOR_OVERLOADS
inline __m128 operator+(const __m128 A, const __m128 B)
{
return _mm_add_ps(A, B);
@@ -308,7 +312,7 @@ inline __m128 operator*(const __m128 A, const __m128 B)
{
return _mm_mul_ps(A, B);
}
-
+#endif //B3_NO_SIMD_OPERATOR_OVERLOADS
#define b3CastfTo128i(a) (_mm_castps_si128(a))
#define b3CastfTo128d(a) (_mm_castps_pd(a))
#define b3CastiTo128f(a) (_mm_castsi128_ps(a))
diff --git a/thirdparty/bullet/Bullet3OpenCL/BroadphaseCollision/b3GpuParallelLinearBvh.cpp b/thirdparty/bullet/Bullet3OpenCL/BroadphaseCollision/b3GpuParallelLinearBvh.cpp
index 0721928684..616fc34f3a 100644
--- a/thirdparty/bullet/Bullet3OpenCL/BroadphaseCollision/b3GpuParallelLinearBvh.cpp
+++ b/thirdparty/bullet/Bullet3OpenCL/BroadphaseCollision/b3GpuParallelLinearBvh.cpp
@@ -496,7 +496,7 @@ void b3GpuParallelLinearBvh::constructBinaryRadixTree()
clFinish(m_queue);
}
- //Find the number of nodes seperating each internal node and the root node
+ //Find the number of nodes separating each internal node and the root node
//so that the AABBs can be set using the next kernel.
//Also determine the maximum number of nodes separating an internal node and the root node.
{
diff --git a/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3StridingMeshInterface.h b/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3StridingMeshInterface.h
index 087b30f3e6..2b1e63be75 100644
--- a/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3StridingMeshInterface.h
+++ b/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3StridingMeshInterface.h
@@ -68,7 +68,7 @@ public:
virtual void unLockReadOnlyVertexBase(int subpart) const = 0;
- /// getNumSubParts returns the number of seperate subparts
+ /// getNumSubParts returns the number of separate subparts
/// each subpart has a continuous array of vertices and indices
virtual int getNumSubParts() const = 0;
diff --git a/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3TriangleIndexVertexArray.h b/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3TriangleIndexVertexArray.h
index b6ceb8df10..57cbf03dc2 100644
--- a/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3TriangleIndexVertexArray.h
+++ b/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3TriangleIndexVertexArray.h
@@ -100,7 +100,7 @@ public:
virtual void unLockReadOnlyVertexBase(int subpart) const { (void)subpart; }
- /// getNumSubParts returns the number of seperate subparts
+ /// getNumSubParts returns the number of separate subparts
/// each subpart has a continuous array of vertices and indices
virtual int getNumSubParts() const
{
diff --git a/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3VoronoiSimplexSolver.cpp b/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3VoronoiSimplexSolver.cpp
index dae61d4581..8b0a834efe 100644
--- a/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3VoronoiSimplexSolver.cpp
+++ b/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3VoronoiSimplexSolver.cpp
@@ -183,9 +183,9 @@ bool b3VoronoiSimplexSolver::updateClosestVectorAndPoints()
const b3Vector3& c = m_simplexVectorW[2];
const b3Vector3& d = m_simplexVectorW[3];
- bool hasSeperation = closestPtPointTetrahedron(p, a, b, c, d, m_cachedBC);
+ bool hasSeparation = closestPtPointTetrahedron(p, a, b, c, d, m_cachedBC);
- if (hasSeperation)
+ if (hasSeparation)
{
m_cachedP1 = m_simplexPointsP[0] * m_cachedBC.m_barycentricCoords[0] +
m_simplexPointsP[1] * m_cachedBC.m_barycentricCoords[1] +
diff --git a/thirdparty/bullet/BulletCollision/BroadphaseCollision/btBroadphaseProxy.h b/thirdparty/bullet/BulletCollision/BroadphaseCollision/btBroadphaseProxy.h
index 825caeef56..bc0742ad62 100644
--- a/thirdparty/bullet/BulletCollision/BroadphaseCollision/btBroadphaseProxy.h
+++ b/thirdparty/bullet/BulletCollision/BroadphaseCollision/btBroadphaseProxy.h
@@ -187,13 +187,6 @@ btBroadphasePair
BT_DECLARE_ALIGNED_ALLOCATOR();
- btBroadphasePair(const btBroadphasePair& other)
- : m_pProxy0(other.m_pProxy0),
- m_pProxy1(other.m_pProxy1),
- m_algorithm(other.m_algorithm),
- m_internalInfo1(other.m_internalInfo1)
- {
- }
btBroadphasePair(btBroadphaseProxy & proxy0, btBroadphaseProxy & proxy1)
{
//keep them sorted, so the std::set operations work
diff --git a/thirdparty/bullet/BulletCollision/BroadphaseCollision/btDbvt.h b/thirdparty/bullet/BulletCollision/BroadphaseCollision/btDbvt.h
index a316dbf207..980d19a754 100644
--- a/thirdparty/bullet/BulletCollision/BroadphaseCollision/btDbvt.h
+++ b/thirdparty/bullet/BulletCollision/BroadphaseCollision/btDbvt.h
@@ -21,7 +21,6 @@ subject to the following restrictions:
#include "LinearMath/btVector3.h"
#include "LinearMath/btTransform.h"
#include "LinearMath/btAabbUtil2.h"
-
//
// Compile time configuration
//
@@ -131,6 +130,7 @@ subject to the following restrictions:
/* btDbvtAabbMm */
struct btDbvtAabbMm
{
+ DBVT_INLINE btDbvtAabbMm(){}
DBVT_INLINE btVector3 Center() const { return ((mi + mx) / 2); }
DBVT_INLINE btVector3 Lengths() const { return (mx - mi); }
DBVT_INLINE btVector3 Extents() const { return ((mx - mi) / 2); }
@@ -190,6 +190,36 @@ struct btDbvtNode
};
};
+/* btDbv(normal)tNode */
+struct btDbvntNode
+{
+ btDbvtVolume volume;
+ btVector3 normal;
+ btScalar angle;
+ DBVT_INLINE bool isleaf() const { return (childs[1] == 0); }
+ DBVT_INLINE bool isinternal() const { return (!isleaf()); }
+ btDbvntNode* childs[2];
+ void* data;
+
+ btDbvntNode(const btDbvtNode* n)
+ : volume(n->volume)
+ , angle(0)
+ , normal(0,0,0)
+ , data(n->data)
+ {
+ childs[0] = 0;
+ childs[1] = 0;
+ }
+
+ ~btDbvntNode()
+ {
+ if (childs[0])
+ delete childs[0];
+ if (childs[1])
+ delete childs[1];
+ }
+};
+
typedef btAlignedObjectArray<const btDbvtNode*> btNodeStack;
///The btDbvt class implements a fast dynamic bounding volume tree based on axis aligned bounding boxes (aabb tree).
@@ -225,6 +255,14 @@ struct btDbvt
btDbvtNode* parent;
sStkCLN(const btDbvtNode* n, btDbvtNode* p) : node(n), parent(p) {}
};
+
+ struct sStknNN
+ {
+ const btDbvntNode* a;
+ const btDbvntNode* b;
+ sStknNN() {}
+ sStknNN(const btDbvntNode* na, const btDbvntNode* nb) : a(na), b(nb) {}
+ };
// Policies/Interfaces
/* ICollide */
@@ -234,6 +272,7 @@ struct btDbvt
DBVT_VIRTUAL void Process(const btDbvtNode*, const btDbvtNode*) {}
DBVT_VIRTUAL void Process(const btDbvtNode*) {}
DBVT_VIRTUAL void Process(const btDbvtNode* n, btScalar) { Process(n); }
+ DBVT_VIRTUAL void Process(const btDbvntNode*, const btDbvntNode*) {}
DBVT_VIRTUAL bool Descent(const btDbvtNode*) { return (true); }
DBVT_VIRTUAL bool AllLeaves(const btDbvtNode*) { return (true); }
};
@@ -306,6 +345,12 @@ struct btDbvt
void collideTT(const btDbvtNode* root0,
const btDbvtNode* root1,
DBVT_IPOLICY);
+ DBVT_PREFIX
+ void selfCollideT(const btDbvntNode* root,
+ DBVT_IPOLICY);
+ DBVT_PREFIX
+ void selfCollideTT(const btDbvtNode* root,
+ DBVT_IPOLICY);
DBVT_PREFIX
void collideTTpersistentStack(const btDbvtNode* root0,
@@ -837,6 +882,135 @@ inline void btDbvt::collideTT(const btDbvtNode* root0,
}
}
+//
+DBVT_PREFIX
+inline void btDbvt::selfCollideT(const btDbvntNode* root,
+ DBVT_IPOLICY)
+{
+ DBVT_CHECKTYPE
+ if (root)
+ {
+ int depth = 1;
+ int treshold = DOUBLE_STACKSIZE - 4;
+ btAlignedObjectArray<sStknNN> stkStack;
+ stkStack.resize(DOUBLE_STACKSIZE);
+ stkStack[0] = sStknNN(root, root);
+ do
+ {
+ sStknNN p = stkStack[--depth];
+ if (depth > treshold)
+ {
+ stkStack.resize(stkStack.size() * 2);
+ treshold = stkStack.size() - 4;
+ }
+ if (p.a == p.b)
+ {
+ if (p.a->isinternal() && p.a->angle > SIMD_PI)
+ {
+ stkStack[depth++] = sStknNN(p.a->childs[0], p.a->childs[0]);
+ stkStack[depth++] = sStknNN(p.a->childs[1], p.a->childs[1]);
+ stkStack[depth++] = sStknNN(p.a->childs[0], p.a->childs[1]);
+ }
+ }
+ else if (Intersect(p.a->volume, p.b->volume))
+ {
+ if (p.a->isinternal())
+ {
+ if (p.b->isinternal())
+ {
+ stkStack[depth++] = sStknNN(p.a->childs[0], p.b->childs[0]);
+ stkStack[depth++] = sStknNN(p.a->childs[1], p.b->childs[0]);
+ stkStack[depth++] = sStknNN(p.a->childs[0], p.b->childs[1]);
+ stkStack[depth++] = sStknNN(p.a->childs[1], p.b->childs[1]);
+ }
+ else
+ {
+ stkStack[depth++] = sStknNN(p.a->childs[0], p.b);
+ stkStack[depth++] = sStknNN(p.a->childs[1], p.b);
+ }
+ }
+ else
+ {
+ if (p.b->isinternal())
+ {
+ stkStack[depth++] = sStknNN(p.a, p.b->childs[0]);
+ stkStack[depth++] = sStknNN(p.a, p.b->childs[1]);
+ }
+ else
+ {
+ policy.Process(p.a, p.b);
+ }
+ }
+ }
+ } while (depth);
+ }
+}
+
+//
+DBVT_PREFIX
+inline void btDbvt::selfCollideTT(const btDbvtNode* root,
+ DBVT_IPOLICY)
+{
+ DBVT_CHECKTYPE
+ if (root)
+ {
+ int depth = 1;
+ int treshold = DOUBLE_STACKSIZE - 4;
+ btAlignedObjectArray<sStkNN> stkStack;
+ stkStack.resize(DOUBLE_STACKSIZE);
+ stkStack[0] = sStkNN(root, root);
+ do
+ {
+ sStkNN p = stkStack[--depth];
+ if (depth > treshold)
+ {
+ stkStack.resize(stkStack.size() * 2);
+ treshold = stkStack.size() - 4;
+ }
+ if (p.a == p.b)
+ {
+ if (p.a->isinternal())
+ {
+ stkStack[depth++] = sStkNN(p.a->childs[0], p.a->childs[0]);
+ stkStack[depth++] = sStkNN(p.a->childs[1], p.a->childs[1]);
+ stkStack[depth++] = sStkNN(p.a->childs[0], p.a->childs[1]);
+ }
+ }
+ else if (Intersect(p.a->volume, p.b->volume))
+ {
+ if (p.a->isinternal())
+ {
+ if (p.b->isinternal())
+ {
+ stkStack[depth++] = sStkNN(p.a->childs[0], p.b->childs[0]);
+ stkStack[depth++] = sStkNN(p.a->childs[1], p.b->childs[0]);
+ stkStack[depth++] = sStkNN(p.a->childs[0], p.b->childs[1]);
+ stkStack[depth++] = sStkNN(p.a->childs[1], p.b->childs[1]);
+ }
+ else
+ {
+ stkStack[depth++] = sStkNN(p.a->childs[0], p.b);
+ stkStack[depth++] = sStkNN(p.a->childs[1], p.b);
+ }
+ }
+ else
+ {
+ if (p.b->isinternal())
+ {
+ stkStack[depth++] = sStkNN(p.a, p.b->childs[0]);
+ stkStack[depth++] = sStkNN(p.a, p.b->childs[1]);
+ }
+ else
+ {
+ policy.Process(p.a, p.b);
+ }
+ }
+ }
+ } while (depth);
+ }
+}
+
+
DBVT_PREFIX
inline void btDbvt::collideTTpersistentStack(const btDbvtNode* root0,
const btDbvtNode* root1,
diff --git a/thirdparty/bullet/BulletCollision/BroadphaseCollision/btOverlappingPairCache.h b/thirdparty/bullet/BulletCollision/BroadphaseCollision/btOverlappingPairCache.h
index a85782bc8a..f4a2d5e368 100644
--- a/thirdparty/bullet/BulletCollision/BroadphaseCollision/btOverlappingPairCache.h
+++ b/thirdparty/bullet/BulletCollision/BroadphaseCollision/btOverlappingPairCache.h
@@ -68,7 +68,7 @@ public:
virtual void processAllOverlappingPairs(btOverlapCallback*, btDispatcher* dispatcher) = 0;
- virtual void processAllOverlappingPairs(btOverlapCallback* callback, btDispatcher* dispatcher, const struct btDispatcherInfo& dispatchInfo)
+ virtual void processAllOverlappingPairs(btOverlapCallback* callback, btDispatcher* dispatcher, const struct btDispatcherInfo& /*dispatchInfo*/)
{
processAllOverlappingPairs(callback, dispatcher);
}
diff --git a/thirdparty/bullet/BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h b/thirdparty/bullet/BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h
index 1cc4a5ac5f..56341b7d29 100644
--- a/thirdparty/bullet/BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h
+++ b/thirdparty/bullet/BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h
@@ -27,13 +27,19 @@ public:
const btCollisionShape* m_shape;
const btCollisionObject* m_collisionObject;
const btTransform& m_worldTransform;
+ const btTransform* m_preTransform;
int m_partId;
int m_index;
btCollisionObjectWrapper(const btCollisionObjectWrapper* parent, const btCollisionShape* shape, const btCollisionObject* collisionObject, const btTransform& worldTransform, int partId, int index)
- : m_parent(parent), m_shape(shape), m_collisionObject(collisionObject), m_worldTransform(worldTransform), m_partId(partId), m_index(index)
+ : m_parent(parent), m_shape(shape), m_collisionObject(collisionObject), m_worldTransform(worldTransform), m_preTransform(NULL), m_partId(partId), m_index(index)
{
}
+
+ btCollisionObjectWrapper(const btCollisionObjectWrapper* parent, const btCollisionShape* shape, const btCollisionObject* collisionObject, const btTransform& worldTransform, const btTransform& preTransform, int partId, int index)
+ : m_parent(parent), m_shape(shape), m_collisionObject(collisionObject), m_worldTransform(worldTransform), m_preTransform(&preTransform), m_partId(partId), m_index(index)
+ {
+ }
SIMD_FORCE_INLINE const btTransform& getWorldTransform() const { return m_worldTransform; }
SIMD_FORCE_INLINE const btCollisionObject* getCollisionObject() const { return m_collisionObject; }
diff --git a/thirdparty/bullet/BulletCollision/CollisionDispatch/btCollisionWorldImporter.cpp b/thirdparty/bullet/BulletCollision/CollisionDispatch/btCollisionWorldImporter.cpp
index 9f422dc157..e56e73dcf5 100644
--- a/thirdparty/bullet/BulletCollision/CollisionDispatch/btCollisionWorldImporter.cpp
+++ b/thirdparty/bullet/BulletCollision/CollisionDispatch/btCollisionWorldImporter.cpp
@@ -292,8 +292,8 @@ btCollisionShape* btCollisionWorldImporter::convertCollisionShape(btCollisionSha
}
break;
}
-#endif //SUPPORT_GIMPACT_SHAPE_IMPORT \
- //The btCapsuleShape* API has issue passing the margin/scaling/halfextents unmodified through the API \
+#endif //SUPPORT_GIMPACT_SHAPE_IMPORT
+ //The btCapsuleShape* API has issue passing the margin/scaling/halfextents unmodified through the API
//so deal with this
case CAPSULE_SHAPE_PROXYTYPE:
{
diff --git a/thirdparty/bullet/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.cpp b/thirdparty/bullet/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.cpp
index 633bee4825..1bb21104cb 100644
--- a/thirdparty/bullet/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.cpp
+++ b/thirdparty/bullet/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.cpp
@@ -139,7 +139,7 @@ public:
if (TestAabbAgainstAabb2(aabbMin0, aabbMax0, aabbMin1, aabbMax1))
{
- btCollisionObjectWrapper compoundWrap(this->m_compoundColObjWrap, childShape, m_compoundColObjWrap->getCollisionObject(), newChildWorldTrans, -1, index);
+ btCollisionObjectWrapper compoundWrap(this->m_compoundColObjWrap, childShape, m_compoundColObjWrap->getCollisionObject(), newChildWorldTrans, childTrans, -1, index);
btCollisionAlgorithm* algo = 0;
bool allocatedAlgorithm = false;
diff --git a/thirdparty/bullet/BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.cpp b/thirdparty/bullet/BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.cpp
index 44dd3c553e..b48d97f2b2 100644
--- a/thirdparty/bullet/BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.cpp
+++ b/thirdparty/bullet/BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.cpp
@@ -503,9 +503,9 @@ void btConvexConvexAlgorithm ::processCollision(const btCollisionObjectWrapper*
gjkPairDetector.getClosestPoints(input, withoutMargin, dispatchInfo.m_debugDraw);
//gjkPairDetector.getClosestPoints(input,dummy,dispatchInfo.m_debugDraw);
-#endif //ZERO_MARGIN \
- //btScalar l2 = gjkPairDetector.getCachedSeparatingAxis().length2(); \
- //if (l2>SIMD_EPSILON)
+#endif //ZERO_MARGIN
+ //btScalar l2 = gjkPairDetector.getCachedSeparatingAxis().length2();
+ //if (l2>SIMD_EPSILON)
{
sepNormalWorldSpace = withoutMargin.m_reportedNormalOnWorld; //gjkPairDetector.getCachedSeparatingAxis()*(1.f/l2);
//minDist = -1e30f;//gjkPairDetector.getCachedSeparatingDistance();
diff --git a/thirdparty/bullet/BulletCollision/CollisionDispatch/btInternalEdgeUtility.cpp b/thirdparty/bullet/BulletCollision/CollisionDispatch/btInternalEdgeUtility.cpp
index e74c83f9f1..a4252c296a 100644
--- a/thirdparty/bullet/BulletCollision/CollisionDispatch/btInternalEdgeUtility.cpp
+++ b/thirdparty/bullet/BulletCollision/CollisionDispatch/btInternalEdgeUtility.cpp
@@ -1,6 +1,8 @@
#include "btInternalEdgeUtility.h"
#include "BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h"
+#include "BulletCollision/CollisionShapes/btHeightfieldTerrainShape.h"
+
#include "BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.h"
#include "BulletCollision/CollisionShapes/btTriangleShape.h"
#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
@@ -290,6 +292,39 @@ struct btConnectivityProcessor : public btTriangleCallback
}
}
};
+
+
+struct b3ProcessAllTrianglesHeightfield: public btTriangleCallback
+{
+ btHeightfieldTerrainShape* m_heightfieldShape;
+ btTriangleInfoMap* m_triangleInfoMap;
+
+
+ b3ProcessAllTrianglesHeightfield(btHeightfieldTerrainShape* heightFieldShape, btTriangleInfoMap* triangleInfoMap)
+ :m_heightfieldShape(heightFieldShape),
+ m_triangleInfoMap(triangleInfoMap)
+ {
+ }
+ virtual void processTriangle(btVector3* triangle, int partId, int triangleIndex)
+ {
+ btConnectivityProcessor connectivityProcessor;
+ connectivityProcessor.m_partIdA = partId;
+ connectivityProcessor.m_triangleIndexA = triangleIndex;
+ connectivityProcessor.m_triangleVerticesA = triangle;
+ connectivityProcessor.m_triangleInfoMap = m_triangleInfoMap;
+ btVector3 aabbMin, aabbMax;
+ aabbMin.setValue(btScalar(BT_LARGE_FLOAT), btScalar(BT_LARGE_FLOAT), btScalar(BT_LARGE_FLOAT));
+ aabbMax.setValue(btScalar(-BT_LARGE_FLOAT), btScalar(-BT_LARGE_FLOAT), btScalar(-BT_LARGE_FLOAT));
+ aabbMin.setMin(triangle[0]);
+ aabbMax.setMax(triangle[0]);
+ aabbMin.setMin(triangle[1]);
+ aabbMax.setMax(triangle[1]);
+ aabbMin.setMin(triangle[2]);
+ aabbMax.setMax(triangle[2]);
+
+ m_heightfieldShape->processAllTriangles(&connectivityProcessor, aabbMin, aabbMax);
+ }
+};
/////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////
@@ -361,6 +396,28 @@ void btGenerateInternalEdgeInfo(btBvhTriangleMeshShape* trimeshShape, btTriangle
}
}
+
+void btGenerateInternalEdgeInfo(btHeightfieldTerrainShape* heightfieldShape, btTriangleInfoMap* triangleInfoMap)
+{
+
+ //the user pointer shouldn't already be used for other purposes, we intend to store connectivity info there!
+ if (heightfieldShape->getTriangleInfoMap())
+ return;
+
+ heightfieldShape->setTriangleInfoMap(triangleInfoMap);
+
+ //get all the triangles of the heightfield
+
+ btVector3 aabbMin, aabbMax;
+
+ aabbMax.setValue(btScalar(BT_LARGE_FLOAT), btScalar(BT_LARGE_FLOAT), btScalar(BT_LARGE_FLOAT));
+ aabbMin.setValue(btScalar(-BT_LARGE_FLOAT), btScalar(-BT_LARGE_FLOAT), btScalar(-BT_LARGE_FLOAT));
+
+ b3ProcessAllTrianglesHeightfield processHeightfield(heightfieldShape, triangleInfoMap);
+ heightfieldShape->processAllTriangles(&processHeightfield, aabbMin, aabbMax);
+
+}
+
// Given a point and a line segment (defined by two points), compute the closest point
// in the line. Cap the point at the endpoints of the line segment.
void btNearestPointInLineSegment(const btVector3& point, const btVector3& line0, const btVector3& line1, btVector3& nearestPoint)
@@ -426,6 +483,32 @@ void btAdjustInternalEdgeContacts(btManifoldPoint& cp, const btCollisionObjectWr
if (colObj0Wrap->getCollisionShape()->getShapeType() != TRIANGLE_SHAPE_PROXYTYPE)
return;
+
+ btTriangleInfoMap* triangleInfoMapPtr = 0;
+
+ if (colObj0Wrap->getCollisionObject()->getCollisionShape()->getShapeType() == TERRAIN_SHAPE_PROXYTYPE)
+ {
+ btHeightfieldTerrainShape* heightfield = (btHeightfieldTerrainShape*)colObj0Wrap->getCollisionObject()->getCollisionShape();
+ triangleInfoMapPtr = heightfield->getTriangleInfoMap();
+
+//#define USE_HEIGHTFIELD_TRIANGLES
+#ifdef USE_HEIGHTFIELD_TRIANGLES
+ btVector3 newNormal = btVector3(0, 0, 1);
+
+ const btTriangleShape* tri_shape = static_cast<const btTriangleShape*>(colObj0Wrap->getCollisionShape());
+ btVector3 tri_normal;
+ tri_shape->calcNormal(tri_normal);
+ newNormal = tri_normal;
+ // cp.m_distance1 = cp.m_distance1 * newNormal.dot(cp.m_normalWorldOnB);
+ cp.m_normalWorldOnB = newNormal;
+ // Reproject collision point along normal. (what about cp.m_distance1?)
+ cp.m_positionWorldOnB = cp.m_positionWorldOnA - cp.m_normalWorldOnB * cp.m_distance1;
+ cp.m_localPointB = colObj0Wrap->getWorldTransform().invXform(cp.m_positionWorldOnB);
+ return;
+#endif
+ }
+
+
btBvhTriangleMeshShape* trimesh = 0;
if (colObj0Wrap->getCollisionObject()->getCollisionShape()->getShapeType() == SCALED_TRIANGLE_MESH_SHAPE_PROXYTYPE)
@@ -439,10 +522,12 @@ void btAdjustInternalEdgeContacts(btManifoldPoint& cp, const btCollisionObjectWr
trimesh = (btBvhTriangleMeshShape*)colObj0Wrap->getCollisionObject()->getCollisionShape();
}
}
- if (trimesh == 0)
- return;
-
- btTriangleInfoMap* triangleInfoMapPtr = (btTriangleInfoMap*)trimesh->getTriangleInfoMap();
+ if (trimesh)
+ {
+ triangleInfoMapPtr = (btTriangleInfoMap*)trimesh->getTriangleInfoMap();
+ }
+
+
if (!triangleInfoMapPtr)
return;
diff --git a/thirdparty/bullet/BulletCollision/CollisionDispatch/btInternalEdgeUtility.h b/thirdparty/bullet/BulletCollision/CollisionDispatch/btInternalEdgeUtility.h
index 9d9cff040f..cc6d11c241 100644
--- a/thirdparty/bullet/BulletCollision/CollisionDispatch/btInternalEdgeUtility.h
+++ b/thirdparty/bullet/BulletCollision/CollisionDispatch/btInternalEdgeUtility.h
@@ -15,6 +15,7 @@ class btCollisionObject;
struct btCollisionObjectWrapper;
class btManifoldPoint;
class btIDebugDraw;
+class btHeightfieldTerrainShape;
enum btInternalEdgeAdjustFlags
{
@@ -26,6 +27,8 @@ enum btInternalEdgeAdjustFlags
///Call btGenerateInternalEdgeInfo to create triangle info, store in the shape 'userInfo'
void btGenerateInternalEdgeInfo(btBvhTriangleMeshShape* trimeshShape, btTriangleInfoMap* triangleInfoMap);
+void btGenerateInternalEdgeInfo(btHeightfieldTerrainShape* trimeshShape, btTriangleInfoMap* triangleInfoMap);
+
///Call the btFixMeshNormal to adjust the collision normal, using the triangle info map (generated using btGenerateInternalEdgeInfo)
///If this info map is missing, or the triangle is not store in this map, nothing will be done
void btAdjustInternalEdgeContacts(btManifoldPoint& cp, const btCollisionObjectWrapper* trimeshColObj0Wrap, const btCollisionObjectWrapper* otherColObj1Wrap, int partId0, int index0, int normalAdjustFlags = 0);
diff --git a/thirdparty/bullet/BulletCollision/CollisionDispatch/btSimulationIslandManager.cpp b/thirdparty/bullet/BulletCollision/CollisionDispatch/btSimulationIslandManager.cpp
index e5097ccbbf..327b3f076a 100644
--- a/thirdparty/bullet/BulletCollision/CollisionDispatch/btSimulationIslandManager.cpp
+++ b/thirdparty/bullet/BulletCollision/CollisionDispatch/btSimulationIslandManager.cpp
@@ -233,7 +233,7 @@ void btSimulationIslandManager::buildIslands(btDispatcher* dispatcher, btCollisi
// printf("error in island management\n");
}
- btAssert((colObj0->getIslandTag() == islandId) || (colObj0->getIslandTag() == -1));
+ btAssert((colObj0->getIslandTag() == islandId) || (colObj0->getIslandTag() == -1));
if (colObj0->getIslandTag() == islandId)
{
if (colObj0->getActivationState() == ACTIVE_TAG ||
@@ -257,7 +257,7 @@ void btSimulationIslandManager::buildIslands(btDispatcher* dispatcher, btCollisi
// printf("error in island management\n");
}
- btAssert((colObj0->getIslandTag() == islandId) || (colObj0->getIslandTag() == -1));
+ btAssert((colObj0->getIslandTag() == islandId) || (colObj0->getIslandTag() == -1));
if (colObj0->getIslandTag() == islandId)
{
@@ -278,7 +278,8 @@ void btSimulationIslandManager::buildIslands(btDispatcher* dispatcher, btCollisi
// printf("error in island management\n");
}
- btAssert((colObj0->getIslandTag() == islandId) || (colObj0->getIslandTag() == -1));
+ btAssert((colObj0->getIslandTag() == islandId) || (colObj0->getIslandTag() == -1));
+
if (colObj0->getIslandTag() == islandId)
{
@@ -337,13 +338,17 @@ void btSimulationIslandManager::buildIslands(btDispatcher* dispatcher, btCollisi
}
}
+
///@todo: this is random access, it can be walked 'cache friendly'!
void btSimulationIslandManager::buildAndProcessIslands(btDispatcher* dispatcher, btCollisionWorld* collisionWorld, IslandCallback* callback)
{
- btCollisionObjectArray& collisionObjects = collisionWorld->getCollisionObjectArray();
-
buildIslands(dispatcher, collisionWorld);
+ processIslands(dispatcher, collisionWorld, callback);
+}
+void btSimulationIslandManager::processIslands(btDispatcher* dispatcher, btCollisionWorld* collisionWorld, IslandCallback* callback)
+{
+ btCollisionObjectArray& collisionObjects = collisionWorld->getCollisionObjectArray();
int endIslandIndex = 1;
int startIslandIndex;
int numElem = getUnionFind().getNumElements();
diff --git a/thirdparty/bullet/BulletCollision/CollisionDispatch/btSimulationIslandManager.h b/thirdparty/bullet/BulletCollision/CollisionDispatch/btSimulationIslandManager.h
index 6c2802141c..197bb457cf 100644
--- a/thirdparty/bullet/BulletCollision/CollisionDispatch/btSimulationIslandManager.h
+++ b/thirdparty/bullet/BulletCollision/CollisionDispatch/btSimulationIslandManager.h
@@ -57,9 +57,11 @@ public:
};
void buildAndProcessIslands(btDispatcher* dispatcher, btCollisionWorld* collisionWorld, IslandCallback* callback);
-
+
void buildIslands(btDispatcher* dispatcher, btCollisionWorld* colWorld);
+ void processIslands(btDispatcher* dispatcher, btCollisionWorld* collisionWorld, IslandCallback* callback);
+
bool getSplitIslands()
{
return m_splitIslands;
diff --git a/thirdparty/bullet/BulletCollision/CollisionShapes/btHeightfieldTerrainShape.cpp b/thirdparty/bullet/BulletCollision/CollisionShapes/btHeightfieldTerrainShape.cpp
index 34ec2d8c45..34e7926f17 100644
--- a/thirdparty/bullet/BulletCollision/CollisionShapes/btHeightfieldTerrainShape.cpp
+++ b/thirdparty/bullet/BulletCollision/CollisionShapes/btHeightfieldTerrainShape.cpp
@@ -21,6 +21,9 @@ btHeightfieldTerrainShape::btHeightfieldTerrainShape(
int heightStickWidth, int heightStickLength, const void* heightfieldData,
btScalar heightScale, btScalar minHeight, btScalar maxHeight, int upAxis,
PHY_ScalarType hdt, bool flipQuadEdges)
+ :m_userIndex2(-1),
+ m_userValue3(0),
+ m_triangleInfoMap(0)
{
initialize(heightStickWidth, heightStickLength, heightfieldData,
heightScale, minHeight, maxHeight, upAxis, hdt,
@@ -28,6 +31,9 @@ btHeightfieldTerrainShape::btHeightfieldTerrainShape(
}
btHeightfieldTerrainShape::btHeightfieldTerrainShape(int heightStickWidth, int heightStickLength, const void* heightfieldData, btScalar maxHeight, int upAxis, bool useFloatData, bool flipQuadEdges)
+ :m_userIndex2(-1),
+ m_userValue3(0),
+ m_triangleInfoMap(0)
{
// legacy constructor: support only float or unsigned char,
// and min height is zero
@@ -349,12 +355,12 @@ void btHeightfieldTerrainShape::processAllTriangles(btTriangleCallback* callback
getVertex(x, j, vertices[indices[0]]);
getVertex(x, j + 1, vertices[indices[1]]);
getVertex(x + 1, j + 1, vertices[indices[2]]);
- callback->processTriangle(vertices, x, j);
+ callback->processTriangle(vertices, 2 * x, j);
//second triangle
// getVertex(x,j,vertices[0]);//already got this vertex before, thanks to Danny Chapman
getVertex(x + 1, j + 1, vertices[indices[1]]);
getVertex(x + 1, j, vertices[indices[2]]);
- callback->processTriangle(vertices, x, j);
+ callback->processTriangle(vertices, 2 * x+1, j);
}
else
{
@@ -362,12 +368,12 @@ void btHeightfieldTerrainShape::processAllTriangles(btTriangleCallback* callback
getVertex(x, j, vertices[indices[0]]);
getVertex(x, j + 1, vertices[indices[1]]);
getVertex(x + 1, j, vertices[indices[2]]);
- callback->processTriangle(vertices, x, j);
+ callback->processTriangle(vertices, 2 * x, j);
//second triangle
getVertex(x + 1, j, vertices[indices[0]]);
//getVertex(x,j+1,vertices[1]);
getVertex(x + 1, j + 1, vertices[indices[2]]);
- callback->processTriangle(vertices, x, j);
+ callback->processTriangle(vertices, 2 * x+1, j);
}
}
}
diff --git a/thirdparty/bullet/BulletCollision/CollisionShapes/btHeightfieldTerrainShape.h b/thirdparty/bullet/BulletCollision/CollisionShapes/btHeightfieldTerrainShape.h
index 43e1d25e3d..8dea98fc6b 100644
--- a/thirdparty/bullet/BulletCollision/CollisionShapes/btHeightfieldTerrainShape.h
+++ b/thirdparty/bullet/BulletCollision/CollisionShapes/btHeightfieldTerrainShape.h
@@ -114,6 +114,11 @@ protected:
int m_vboundsGridLength;
int m_vboundsChunkSize;
+ int m_userIndex2;
+ btScalar m_userValue3;
+
+ struct btTriangleInfoMap* m_triangleInfoMap;
+
virtual btScalar getRawHeightFieldValue(int x, int y) const;
void quantizeWithClamp(int* out, const btVector3& point, int isMax) const;
@@ -185,6 +190,40 @@ public:
}
//debugging
virtual const char* getName() const { return "HEIGHTFIELD"; }
+
+
+ void setUserIndex2(int index)
+ {
+ m_userIndex2 = index;
+ }
+ int getUserIndex2() const
+ {
+ return m_userIndex2;
+ }
+ void setUserValue3(btScalar value)
+ {
+ m_userValue3 = value;
+ }
+ btScalar getUserValue3() const
+ {
+ return m_userValue3;
+ }
+ const struct btTriangleInfoMap* getTriangleInfoMap() const
+ {
+ return m_triangleInfoMap;
+ }
+ struct btTriangleInfoMap* getTriangleInfoMap()
+ {
+ return m_triangleInfoMap;
+ }
+ void setTriangleInfoMap(btTriangleInfoMap* map)
+ {
+ m_triangleInfoMap = map;
+ }
+ const unsigned char* getHeightfieldRawData() const
+ {
+ return m_heightfieldDataUnsignedChar;
+ }
};
#endif //BT_HEIGHTFIELD_TERRAIN_SHAPE_H \ No newline at end of file
diff --git a/thirdparty/bullet/BulletCollision/CollisionShapes/btStridingMeshInterface.h b/thirdparty/bullet/BulletCollision/CollisionShapes/btStridingMeshInterface.h
index 7d729ee0d7..68a41dfb45 100644
--- a/thirdparty/bullet/BulletCollision/CollisionShapes/btStridingMeshInterface.h
+++ b/thirdparty/bullet/BulletCollision/CollisionShapes/btStridingMeshInterface.h
@@ -58,7 +58,7 @@ public:
virtual void unLockReadOnlyVertexBase(int subpart) const = 0;
- /// getNumSubParts returns the number of seperate subparts
+ /// getNumSubParts returns the number of separate subparts
/// each subpart has a continuous array of vertices and indices
virtual int getNumSubParts() const = 0;
diff --git a/thirdparty/bullet/BulletCollision/CollisionShapes/btTriangleIndexVertexArray.h b/thirdparty/bullet/BulletCollision/CollisionShapes/btTriangleIndexVertexArray.h
index 8ebb22baae..556aa3fef4 100644
--- a/thirdparty/bullet/BulletCollision/CollisionShapes/btTriangleIndexVertexArray.h
+++ b/thirdparty/bullet/BulletCollision/CollisionShapes/btTriangleIndexVertexArray.h
@@ -100,7 +100,7 @@ public:
virtual void unLockReadOnlyVertexBase(int subpart) const { (void)subpart; }
- /// getNumSubParts returns the number of seperate subparts
+ /// getNumSubParts returns the number of separate subparts
/// each subpart has a continuous array of vertices and indices
virtual int getNumSubParts() const
{
diff --git a/thirdparty/bullet/BulletCollision/Gimpact/btGImpactShape.h b/thirdparty/bullet/BulletCollision/Gimpact/btGImpactShape.h
index eb33ce05e2..5b85e87041 100644
--- a/thirdparty/bullet/BulletCollision/Gimpact/btGImpactShape.h
+++ b/thirdparty/bullet/BulletCollision/Gimpact/btGImpactShape.h
@@ -1,5 +1,5 @@
/*! \file btGImpactShape.h
-\author Francisco Leon Najera
+\author Francisco Len Nßjera
*/
/*
This source file is part of GIMPACT Library.
diff --git a/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btComputeGjkEpaPenetration.h b/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btComputeGjkEpaPenetration.h
index c94391d816..3c82133037 100644
--- a/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btComputeGjkEpaPenetration.h
+++ b/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btComputeGjkEpaPenetration.h
@@ -95,11 +95,11 @@ int btComputeGjkEpaPenetration(const btConvexTemplate& a, const btConvexTemplate
for (;;)
//while (true)
{
- btVector3 seperatingAxisInA = (-m_cachedSeparatingAxis) * localTransA.getBasis();
- btVector3 seperatingAxisInB = m_cachedSeparatingAxis * localTransB.getBasis();
+ btVector3 separatingAxisInA = (-m_cachedSeparatingAxis) * localTransA.getBasis();
+ btVector3 separatingAxisInB = m_cachedSeparatingAxis * localTransB.getBasis();
- btVector3 pInA = a.getLocalSupportWithoutMargin(seperatingAxisInA);
- btVector3 qInB = b.getLocalSupportWithoutMargin(seperatingAxisInB);
+ btVector3 pInA = a.getLocalSupportWithoutMargin(separatingAxisInA);
+ btVector3 qInB = b.getLocalSupportWithoutMargin(separatingAxisInB);
btVector3 pWorld = localTransA(pInA);
btVector3 qWorld = localTransB(qInB);
diff --git a/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btGjkPairDetector.cpp b/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btGjkPairDetector.cpp
index 4339b2ea75..5af93cb2fb 100644
--- a/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btGjkPairDetector.cpp
+++ b/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btGjkPairDetector.cpp
@@ -79,11 +79,11 @@ void btGjkPairDetector::getClosestPoints(const ClosestPointInput &input, Result
static void btComputeSupport(const btConvexShape *convexA, const btTransform &localTransA, const btConvexShape *convexB, const btTransform &localTransB, const btVector3 &dir, bool check2d, btVector3 &supAworld, btVector3 &supBworld, btVector3 &aMinb)
{
- btVector3 seperatingAxisInA = (dir)*localTransA.getBasis();
- btVector3 seperatingAxisInB = (-dir) * localTransB.getBasis();
+ btVector3 separatingAxisInA = (dir)*localTransA.getBasis();
+ btVector3 separatingAxisInB = (-dir) * localTransB.getBasis();
- btVector3 pInANoMargin = convexA->localGetSupportVertexWithoutMarginNonVirtual(seperatingAxisInA);
- btVector3 qInBNoMargin = convexB->localGetSupportVertexWithoutMarginNonVirtual(seperatingAxisInB);
+ btVector3 pInANoMargin = convexA->localGetSupportVertexWithoutMarginNonVirtual(separatingAxisInA);
+ btVector3 qInBNoMargin = convexB->localGetSupportVertexWithoutMarginNonVirtual(separatingAxisInB);
btVector3 pInA = pInANoMargin;
btVector3 qInB = qInBNoMargin;
@@ -839,11 +839,11 @@ void btGjkPairDetector::getClosestPointsNonVirtual(const ClosestPointInput &inpu
for (;;)
//while (true)
{
- btVector3 seperatingAxisInA = (-m_cachedSeparatingAxis) * localTransA.getBasis();
- btVector3 seperatingAxisInB = m_cachedSeparatingAxis * localTransB.getBasis();
+ btVector3 separatingAxisInA = (-m_cachedSeparatingAxis) * localTransA.getBasis();
+ btVector3 separatingAxisInB = m_cachedSeparatingAxis * localTransB.getBasis();
- btVector3 pInA = m_minkowskiA->localGetSupportVertexWithoutMarginNonVirtual(seperatingAxisInA);
- btVector3 qInB = m_minkowskiB->localGetSupportVertexWithoutMarginNonVirtual(seperatingAxisInB);
+ btVector3 pInA = m_minkowskiA->localGetSupportVertexWithoutMarginNonVirtual(separatingAxisInA);
+ btVector3 qInB = m_minkowskiB->localGetSupportVertexWithoutMarginNonVirtual(separatingAxisInB);
btVector3 pWorld = localTransA(pInA);
btVector3 qWorld = localTransB(qInB);
@@ -1116,11 +1116,11 @@ void btGjkPairDetector::getClosestPointsNonVirtual(const ClosestPointInput &inpu
btScalar d2 = 0.f;
{
- btVector3 seperatingAxisInA = (-orgNormalInB) * localTransA.getBasis();
- btVector3 seperatingAxisInB = orgNormalInB * localTransB.getBasis();
+ btVector3 separatingAxisInA = (-orgNormalInB) * localTransA.getBasis();
+ btVector3 separatingAxisInB = orgNormalInB * localTransB.getBasis();
- btVector3 pInA = m_minkowskiA->localGetSupportVertexWithoutMarginNonVirtual(seperatingAxisInA);
- btVector3 qInB = m_minkowskiB->localGetSupportVertexWithoutMarginNonVirtual(seperatingAxisInB);
+ btVector3 pInA = m_minkowskiA->localGetSupportVertexWithoutMarginNonVirtual(separatingAxisInA);
+ btVector3 qInB = m_minkowskiB->localGetSupportVertexWithoutMarginNonVirtual(separatingAxisInB);
btVector3 pWorld = localTransA(pInA);
btVector3 qWorld = localTransB(qInB);
@@ -1130,11 +1130,11 @@ void btGjkPairDetector::getClosestPointsNonVirtual(const ClosestPointInput &inpu
btScalar d1 = 0;
{
- btVector3 seperatingAxisInA = (normalInB)*localTransA.getBasis();
- btVector3 seperatingAxisInB = -normalInB * localTransB.getBasis();
+ btVector3 separatingAxisInA = (normalInB)*localTransA.getBasis();
+ btVector3 separatingAxisInB = -normalInB * localTransB.getBasis();
- btVector3 pInA = m_minkowskiA->localGetSupportVertexWithoutMarginNonVirtual(seperatingAxisInA);
- btVector3 qInB = m_minkowskiB->localGetSupportVertexWithoutMarginNonVirtual(seperatingAxisInB);
+ btVector3 pInA = m_minkowskiA->localGetSupportVertexWithoutMarginNonVirtual(separatingAxisInA);
+ btVector3 qInB = m_minkowskiB->localGetSupportVertexWithoutMarginNonVirtual(separatingAxisInB);
btVector3 pWorld = localTransA(pInA);
btVector3 qWorld = localTransB(qInB);
@@ -1143,11 +1143,11 @@ void btGjkPairDetector::getClosestPointsNonVirtual(const ClosestPointInput &inpu
}
btScalar d0 = 0.f;
{
- btVector3 seperatingAxisInA = (-normalInB) * input.m_transformA.getBasis();
- btVector3 seperatingAxisInB = normalInB * input.m_transformB.getBasis();
+ btVector3 separatingAxisInA = (-normalInB) * input.m_transformA.getBasis();
+ btVector3 separatingAxisInB = normalInB * input.m_transformB.getBasis();
- btVector3 pInA = m_minkowskiA->localGetSupportVertexWithoutMarginNonVirtual(seperatingAxisInA);
- btVector3 qInB = m_minkowskiB->localGetSupportVertexWithoutMarginNonVirtual(seperatingAxisInB);
+ btVector3 pInA = m_minkowskiA->localGetSupportVertexWithoutMarginNonVirtual(separatingAxisInA);
+ btVector3 qInB = m_minkowskiB->localGetSupportVertexWithoutMarginNonVirtual(separatingAxisInB);
btVector3 pWorld = localTransA(pInA);
btVector3 qWorld = localTransB(qInB);
diff --git a/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btGjkPairDetector.h b/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btGjkPairDetector.h
index 659b63551e..faa02287ca 100644
--- a/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btGjkPairDetector.h
+++ b/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btGjkPairDetector.h
@@ -64,9 +64,9 @@ public:
{
m_minkowskiB = minkB;
}
- void setCachedSeperatingAxis(const btVector3& seperatingAxis)
+ void setCachedSeparatingAxis(const btVector3& separatingAxis)
{
- m_cachedSeparatingAxis = seperatingAxis;
+ m_cachedSeparatingAxis = separatingAxis;
}
const btVector3& getCachedSeparatingAxis() const
diff --git a/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btManifoldPoint.h b/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btManifoldPoint.h
index 6d21f66202..573fc86bf9 100644
--- a/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btManifoldPoint.h
+++ b/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btManifoldPoint.h
@@ -55,6 +55,7 @@ public:
: m_userPersistentData(0),
m_contactPointFlags(0),
m_appliedImpulse(0.f),
+ m_prevRHS(0.f),
m_appliedImpulseLateral1(0.f),
m_appliedImpulseLateral2(0.f),
m_contactMotion1(0.f),
@@ -79,6 +80,7 @@ public:
m_userPersistentData(0),
m_contactPointFlags(0),
m_appliedImpulse(0.f),
+ m_prevRHS(0.f),
m_appliedImpulseLateral1(0.f),
m_appliedImpulseLateral2(0.f),
m_contactMotion1(0.f),
@@ -114,6 +116,7 @@ public:
int m_contactPointFlags;
btScalar m_appliedImpulse;
+ btScalar m_prevRHS;
btScalar m_appliedImpulseLateral1;
btScalar m_appliedImpulseLateral2;
btScalar m_contactMotion1;
diff --git a/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.cpp b/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.cpp
index a77449812f..c042c24208 100644
--- a/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.cpp
+++ b/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.cpp
@@ -65,7 +65,7 @@ bool btMinkowskiPenetrationDepthSolver::calcPenDepth(btSimplexSolverInterface& s
btScalar minProj = btScalar(BT_LARGE_FLOAT);
btVector3 minNorm(btScalar(0.), btScalar(0.), btScalar(0.));
btVector3 minA, minB;
- btVector3 seperatingAxisInA, seperatingAxisInB;
+ btVector3 separatingAxisInA, separatingAxisInB;
btVector3 pInA, qInB, pWorld, qWorld, w;
#ifndef __SPU__
@@ -75,8 +75,8 @@ bool btMinkowskiPenetrationDepthSolver::calcPenDepth(btSimplexSolverInterface& s
btVector3 supportVerticesABatch[NUM_UNITSPHERE_POINTS + MAX_PREFERRED_PENETRATION_DIRECTIONS * 2];
btVector3 supportVerticesBBatch[NUM_UNITSPHERE_POINTS + MAX_PREFERRED_PENETRATION_DIRECTIONS * 2];
- btVector3 seperatingAxisInABatch[NUM_UNITSPHERE_POINTS + MAX_PREFERRED_PENETRATION_DIRECTIONS * 2];
- btVector3 seperatingAxisInBBatch[NUM_UNITSPHERE_POINTS + MAX_PREFERRED_PENETRATION_DIRECTIONS * 2];
+ btVector3 separatingAxisInABatch[NUM_UNITSPHERE_POINTS + MAX_PREFERRED_PENETRATION_DIRECTIONS * 2];
+ btVector3 separatingAxisInBBatch[NUM_UNITSPHERE_POINTS + MAX_PREFERRED_PENETRATION_DIRECTIONS * 2];
int i;
int numSampleDirections = NUM_UNITSPHERE_POINTS;
@@ -84,8 +84,8 @@ bool btMinkowskiPenetrationDepthSolver::calcPenDepth(btSimplexSolverInterface& s
for (i = 0; i < numSampleDirections; i++)
{
btVector3 norm = getPenetrationDirections()[i];
- seperatingAxisInABatch[i] = (-norm) * transA.getBasis();
- seperatingAxisInBBatch[i] = norm * transB.getBasis();
+ separatingAxisInABatch[i] = (-norm) * transA.getBasis();
+ separatingAxisInBBatch[i] = norm * transB.getBasis();
}
{
@@ -98,8 +98,8 @@ bool btMinkowskiPenetrationDepthSolver::calcPenDepth(btSimplexSolverInterface& s
convexA->getPreferredPenetrationDirection(i, norm);
norm = transA.getBasis() * norm;
getPenetrationDirections()[numSampleDirections] = norm;
- seperatingAxisInABatch[numSampleDirections] = (-norm) * transA.getBasis();
- seperatingAxisInBBatch[numSampleDirections] = norm * transB.getBasis();
+ separatingAxisInABatch[numSampleDirections] = (-norm) * transA.getBasis();
+ separatingAxisInBBatch[numSampleDirections] = norm * transB.getBasis();
numSampleDirections++;
}
}
@@ -115,15 +115,15 @@ bool btMinkowskiPenetrationDepthSolver::calcPenDepth(btSimplexSolverInterface& s
convexB->getPreferredPenetrationDirection(i, norm);
norm = transB.getBasis() * norm;
getPenetrationDirections()[numSampleDirections] = norm;
- seperatingAxisInABatch[numSampleDirections] = (-norm) * transA.getBasis();
- seperatingAxisInBBatch[numSampleDirections] = norm * transB.getBasis();
+ separatingAxisInABatch[numSampleDirections] = (-norm) * transA.getBasis();
+ separatingAxisInBBatch[numSampleDirections] = norm * transB.getBasis();
numSampleDirections++;
}
}
}
- convexA->batchedUnitVectorGetSupportingVertexWithoutMargin(seperatingAxisInABatch, supportVerticesABatch, numSampleDirections);
- convexB->batchedUnitVectorGetSupportingVertexWithoutMargin(seperatingAxisInBBatch, supportVerticesBBatch, numSampleDirections);
+ convexA->batchedUnitVectorGetSupportingVertexWithoutMargin(separatingAxisInABatch, supportVerticesABatch, numSampleDirections);
+ convexB->batchedUnitVectorGetSupportingVertexWithoutMargin(separatingAxisInBBatch, supportVerticesBBatch, numSampleDirections);
for (i = 0; i < numSampleDirections; i++)
{
@@ -134,8 +134,8 @@ bool btMinkowskiPenetrationDepthSolver::calcPenDepth(btSimplexSolverInterface& s
}
if (norm.length2() > 0.01)
{
- seperatingAxisInA = seperatingAxisInABatch[i];
- seperatingAxisInB = seperatingAxisInBBatch[i];
+ separatingAxisInA = separatingAxisInABatch[i];
+ separatingAxisInB = separatingAxisInBBatch[i];
pInA = supportVerticesABatch[i];
qInB = supportVerticesBBatch[i];
@@ -199,10 +199,10 @@ bool btMinkowskiPenetrationDepthSolver::calcPenDepth(btSimplexSolverInterface& s
for (int i = 0; i < numSampleDirections; i++)
{
const btVector3& norm = getPenetrationDirections()[i];
- seperatingAxisInA = (-norm) * transA.getBasis();
- seperatingAxisInB = norm * transB.getBasis();
- pInA = convexA->localGetSupportVertexWithoutMarginNonVirtual(seperatingAxisInA);
- qInB = convexB->localGetSupportVertexWithoutMarginNonVirtual(seperatingAxisInB);
+ separatingAxisInA = (-norm) * transA.getBasis();
+ separatingAxisInB = norm * transB.getBasis();
+ pInA = convexA->localGetSupportVertexWithoutMarginNonVirtual(separatingAxisInA);
+ qInB = convexB->localGetSupportVertexWithoutMarginNonVirtual(separatingAxisInB);
pWorld = transA(pInA);
qWorld = transB(qInB);
w = qWorld - pWorld;
@@ -259,7 +259,7 @@ bool btMinkowskiPenetrationDepthSolver::calcPenDepth(btSimplexSolverInterface& s
input.m_maximumDistanceSquared = btScalar(BT_LARGE_FLOAT); //minProj;
btIntermediateResult res;
- gjkdet.setCachedSeperatingAxis(-minNorm);
+ gjkdet.setCachedSeparatingAxis(-minNorm);
gjkdet.getClosestPoints(input, res, debugDraw);
btScalar correctedMinNorm = minProj - res.m_depth;
diff --git a/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btMprPenetration.h b/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btMprPenetration.h
index 358bc95d81..534a66d3fa 100644
--- a/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btMprPenetration.h
+++ b/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btMprPenetration.h
@@ -309,11 +309,11 @@ inline void btMprSupport(const btConvexTemplate &a, const btConvexTemplate &b,
const btMprCollisionDescription &colDesc,
const btVector3 &dir, btMprSupport_t *supp)
{
- btVector3 seperatingAxisInA = dir * a.getWorldTransform().getBasis();
- btVector3 seperatingAxisInB = -dir * b.getWorldTransform().getBasis();
+ btVector3 separatingAxisInA = dir * a.getWorldTransform().getBasis();
+ btVector3 separatingAxisInB = -dir * b.getWorldTransform().getBasis();
- btVector3 pInA = a.getLocalSupportWithMargin(seperatingAxisInA);
- btVector3 qInB = b.getLocalSupportWithMargin(seperatingAxisInB);
+ btVector3 pInA = a.getLocalSupportWithMargin(separatingAxisInA);
+ btVector3 qInB = b.getLocalSupportWithMargin(separatingAxisInB);
supp->v1 = a.getWorldTransform()(pInA);
supp->v2 = b.getWorldTransform()(qInB);
@@ -467,7 +467,7 @@ static int btRefinePortal(const btConvexTemplate &a, const btConvexTemplate &b,
for (int i = 0; i < BT_MPR_MAX_ITERATIONS; i++)
//while (1)
{
- // compute direction outside the portal (from v0 throught v1,v2,v3
+ // compute direction outside the portal (from v0 through v1,v2,v3
// face)
btPortalDir(portal, &dir);
diff --git a/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btPersistentManifold.cpp b/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btPersistentManifold.cpp
index f1422cad4d..dca3e09267 100644
--- a/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btPersistentManifold.cpp
+++ b/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btPersistentManifold.cpp
@@ -325,6 +325,7 @@ const char* btPersistentManifold::serialize(const class btPersistentManifold* ma
{
const btManifoldPoint& pt = manifold->getContactPoint(i);
dataOut->m_pointCacheAppliedImpulse[i] = pt.m_appliedImpulse;
+ dataOut->m_pointCachePrevRHS[i] = pt.m_prevRHS;
dataOut->m_pointCacheAppliedImpulseLateral1[i] = pt.m_appliedImpulseLateral1;
dataOut->m_pointCacheAppliedImpulseLateral2[i] = pt.m_appliedImpulseLateral2;
pt.m_localPointA.serialize(dataOut->m_pointCacheLocalPointA[i]);
@@ -371,6 +372,7 @@ void btPersistentManifold::deSerialize(const struct btPersistentManifoldDoubleDa
btManifoldPoint& pt = m_pointCache[i];
pt.m_appliedImpulse = manifoldDataPtr->m_pointCacheAppliedImpulse[i];
+ pt.m_prevRHS = manifoldDataPtr->m_pointCachePrevRHS[i];
pt.m_appliedImpulseLateral1 = manifoldDataPtr->m_pointCacheAppliedImpulseLateral1[i];
pt.m_appliedImpulseLateral2 = manifoldDataPtr->m_pointCacheAppliedImpulseLateral2[i];
pt.m_localPointA.deSerializeDouble(manifoldDataPtr->m_pointCacheLocalPointA[i]);
@@ -416,6 +418,7 @@ void btPersistentManifold::deSerialize(const struct btPersistentManifoldFloatDat
btManifoldPoint& pt = m_pointCache[i];
pt.m_appliedImpulse = manifoldDataPtr->m_pointCacheAppliedImpulse[i];
+ pt.m_prevRHS = manifoldDataPtr->m_pointCachePrevRHS[i];
pt.m_appliedImpulseLateral1 = manifoldDataPtr->m_pointCacheAppliedImpulseLateral1[i];
pt.m_appliedImpulseLateral2 = manifoldDataPtr->m_pointCacheAppliedImpulseLateral2[i];
pt.m_localPointA.deSerialize(manifoldDataPtr->m_pointCacheLocalPointA[i]);
@@ -444,4 +447,4 @@ void btPersistentManifold::deSerialize(const struct btPersistentManifoldFloatDat
pt.m_contactMotion1 = manifoldDataPtr->m_pointCacheContactMotion1[i];
pt.m_contactMotion2 = manifoldDataPtr->m_pointCacheContactMotion2[i];
}
-} \ No newline at end of file
+}
diff --git a/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btPersistentManifold.h b/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btPersistentManifold.h
index 8a9134c95c..0e26da0ebe 100644
--- a/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btPersistentManifold.h
+++ b/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btPersistentManifold.h
@@ -173,6 +173,7 @@ public:
//get rid of duplicated userPersistentData pointer
m_pointCache[lastUsedIndex].m_userPersistentData = 0;
m_pointCache[lastUsedIndex].m_appliedImpulse = 0.f;
+ m_pointCache[lastUsedIndex].m_prevRHS = 0.f;
m_pointCache[lastUsedIndex].m_contactPointFlags = 0;
m_pointCache[lastUsedIndex].m_appliedImpulseLateral1 = 0.f;
m_pointCache[lastUsedIndex].m_appliedImpulseLateral2 = 0.f;
@@ -195,6 +196,7 @@ public:
#ifdef MAINTAIN_PERSISTENCY
int lifeTime = m_pointCache[insertIndex].getLifeTime();
btScalar appliedImpulse = m_pointCache[insertIndex].m_appliedImpulse;
+ btScalar prevRHS = m_pointCache[insertIndex].m_prevRHS;
btScalar appliedLateralImpulse1 = m_pointCache[insertIndex].m_appliedImpulseLateral1;
btScalar appliedLateralImpulse2 = m_pointCache[insertIndex].m_appliedImpulseLateral2;
@@ -223,6 +225,7 @@ public:
m_pointCache[insertIndex] = newPoint;
m_pointCache[insertIndex].m_userPersistentData = cache;
m_pointCache[insertIndex].m_appliedImpulse = appliedImpulse;
+ m_pointCache[insertIndex].m_prevRHS = prevRHS;
m_pointCache[insertIndex].m_appliedImpulseLateral1 = appliedLateralImpulse1;
m_pointCache[insertIndex].m_appliedImpulseLateral2 = appliedLateralImpulse2;
}
@@ -276,7 +279,8 @@ struct btPersistentManifoldDoubleData
btVector3DoubleData m_pointCacheLateralFrictionDir2[4];
double m_pointCacheDistance[4];
double m_pointCacheAppliedImpulse[4];
- double m_pointCacheCombinedFriction[4];
+ double m_pointCachePrevRHS[4];
+ double m_pointCacheCombinedFriction[4];
double m_pointCacheCombinedRollingFriction[4];
double m_pointCacheCombinedSpinningFriction[4];
double m_pointCacheCombinedRestitution[4];
@@ -322,6 +326,7 @@ struct btPersistentManifoldFloatData
btVector3FloatData m_pointCacheLateralFrictionDir2[4];
float m_pointCacheDistance[4];
float m_pointCacheAppliedImpulse[4];
+ float m_pointCachePrevRHS[4];
float m_pointCacheCombinedFriction[4];
float m_pointCacheCombinedRollingFriction[4];
float m_pointCacheCombinedSpinningFriction[4];
diff --git a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btBatchedConstraints.cpp b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btBatchedConstraints.cpp
index 2a5efc6495..27f76b8425 100644
--- a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btBatchedConstraints.cpp
+++ b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btBatchedConstraints.cpp
@@ -890,6 +890,8 @@ static void setupSpatialGridBatchesMt(
btVector3 gridExtent = bboxMax - bboxMin;
+ gridExtent.setMax(btVector3(btScalar(1), btScalar(1), btScalar(1)));
+
btVector3 gridCellSize = consExtent;
int gridDim[3];
gridDim[0] = int(1.0 + gridExtent.x() / gridCellSize.x());
diff --git a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btContactSolverInfo.h b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btContactSolverInfo.h
index 63d7c98e16..e82d1b139e 100644
--- a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btContactSolverInfo.h
+++ b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btContactSolverInfo.h
@@ -30,7 +30,8 @@ enum btSolverMode
SOLVER_SIMD = 256,
SOLVER_INTERLEAVE_CONTACT_AND_FRICTION_CONSTRAINTS = 512,
SOLVER_ALLOW_ZERO_LENGTH_FRICTION_DIRECTIONS = 1024,
- SOLVER_DISABLE_IMPLICIT_CONE_FRICTION = 2048
+ SOLVER_DISABLE_IMPLICIT_CONE_FRICTION = 2048,
+ SOLVER_USE_ARTICULATED_WARMSTARTING = 4096,
};
struct btContactSolverInfoData
@@ -45,6 +46,7 @@ struct btContactSolverInfoData
btScalar m_sor; //successive over-relaxation term
btScalar m_erp; //error reduction for non-contact constraints
btScalar m_erp2; //error reduction for contact constraints
+ btScalar m_deformable_erp; //error reduction for deformable constraints
btScalar m_globalCfm; //constraint force mixing for contacts and non-contacts
btScalar m_frictionERP; //error reduction for friction constraints
btScalar m_frictionCFM; //constraint force mixing for friction constraints
@@ -54,7 +56,7 @@ struct btContactSolverInfoData
btScalar m_splitImpulseTurnErp;
btScalar m_linearSlop;
btScalar m_warmstartingFactor;
-
+ btScalar m_articulatedWarmstartingFactor;
int m_solverMode;
int m_restingContactRestitutionThreshold;
int m_minimumSolverBatchSize;
@@ -80,6 +82,7 @@ struct btContactSolverInfo : public btContactSolverInfoData
m_numIterations = 10;
m_erp = btScalar(0.2);
m_erp2 = btScalar(0.2);
+ m_deformable_erp = btScalar(0.);
m_globalCfm = btScalar(0.);
m_frictionERP = btScalar(0.2); //positional friction 'anchors' are disabled by default
m_frictionCFM = btScalar(0.);
@@ -89,6 +92,7 @@ struct btContactSolverInfo : public btContactSolverInfoData
m_splitImpulseTurnErp = 0.1f;
m_linearSlop = btScalar(0.0);
m_warmstartingFactor = btScalar(0.85);
+ m_articulatedWarmstartingFactor = btScalar(0.85);
//m_solverMode = SOLVER_USE_WARMSTARTING | SOLVER_SIMD | SOLVER_DISABLE_VELOCITY_DEPENDENT_FRICTION_DIRECTION|SOLVER_USE_2_FRICTION_DIRECTIONS|SOLVER_ENABLE_FRICTION_DIRECTION_CACHING;// | SOLVER_RANDMIZE_ORDER;
m_solverMode = SOLVER_USE_WARMSTARTING | SOLVER_SIMD; // | SOLVER_RANDMIZE_ORDER;
m_restingContactRestitutionThreshold = 2; //unused as of 2.81
@@ -120,6 +124,7 @@ struct btContactSolverInfoDoubleData
double m_splitImpulseTurnErp;
double m_linearSlop;
double m_warmstartingFactor;
+ double m_articulatedWarmstartingFactor;
double m_maxGyroscopicForce; ///it is only used for 'explicit' version of gyroscopic force
double m_singleAxisRollingFrictionThreshold;
@@ -150,16 +155,17 @@ struct btContactSolverInfoFloatData
float m_linearSlop;
float m_warmstartingFactor;
+ float m_articulatedWarmstartingFactor;
float m_maxGyroscopicForce;
- float m_singleAxisRollingFrictionThreshold;
+ float m_singleAxisRollingFrictionThreshold;
int m_numIterations;
int m_solverMode;
int m_restingContactRestitutionThreshold;
- int m_minimumSolverBatchSize;
+ int m_minimumSolverBatchSize;
int m_splitImpulse;
- char m_padding[4];
+
};
#endif //BT_CONTACT_SOLVER_INFO
diff --git a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btGeneric6DofSpring2Constraint.cpp b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btGeneric6DofSpring2Constraint.cpp
index 9a3b39e6f8..93626f18ff 100644
--- a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btGeneric6DofSpring2Constraint.cpp
+++ b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btGeneric6DofSpring2Constraint.cpp
@@ -32,7 +32,7 @@ Cons:
/*
2007-09-09
-btGeneric6DofConstraint Refactored by Francisco Leon
+btGeneric6DofConstraint Refactored by Francisco Le?n
email: projectileman@yahoo.com
http://gimpact.sf.net
*/
@@ -311,9 +311,9 @@ void btGeneric6DofSpring2Constraint::calculateAngleInfo()
case RO_XYZ:
{
//Is this the "line of nodes" calculation choosing planes YZ (B coordinate system) and xy (A coordinate system)? (http://en.wikipedia.org/wiki/Euler_angles)
- //The two planes are non-homologous, so this is a Tait-Bryan angle formalism and not a proper Euler
+ //The two planes are non-homologous, so this is a Tait Bryan angle formalism and not a proper Euler
//Extrinsic rotations are equal to the reversed order intrinsic rotations so the above xyz extrinsic rotations (axes are fixed) are the same as the zy'x" intrinsic rotations (axes are refreshed after each rotation)
- //that is why xy and YZ planes are chosen (this will describe a zy'x" intrinsic rotation) (see the figure on the left at http://en.wikipedia.org/wiki/Euler_angles under Tait-Bryan angles)
+ //that is why xy and YZ planes are chosen (this will describe a zy'x" intrinsic rotation) (see the figure on the left at http://en.wikipedia.org/wiki/Euler_angles under Tait Bryan angles)
// x' = Nperp = N.cross(axis2)
// y' = N = axis2.cross(axis0)
// z' = z
diff --git a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.cpp b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.cpp
index d3b71e4583..e4da468299 100644
--- a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.cpp
+++ b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.cpp
@@ -394,18 +394,6 @@ btSingleConstraintRowSolver btSequentialImpulseConstraintSolver::getScalarConstr
return gResolveSingleConstraintRowLowerLimit_scalar_reference;
}
-btSingleConstraintRowSolver btSequentialImpulseConstraintSolver::getScalarSplitPenetrationImpulseGeneric()
-{
- return gResolveSplitPenetrationImpulse_scalar_reference;
-}
-
-btSingleConstraintRowSolver btSequentialImpulseConstraintSolver::getSSE2SplitPenetrationImpulseGeneric()
-{
- return gResolveSplitPenetrationImpulse_sse2;
-}
-
-
-
#ifdef USE_SIMD
btSingleConstraintRowSolver btSequentialImpulseConstraintSolver::getSSE2ConstraintRowSolverGeneric()
{
@@ -433,11 +421,6 @@ unsigned long btSequentialImpulseConstraintSolver::btRand2()
return m_btSeed2;
}
-unsigned long btSequentialImpulseConstraintSolver::btRand2a(unsigned long& seed)
-{
- seed = (1664525L * seed + 1013904223L) & 0xffffffff;
- return seed;
-}
//See ODE: adam's all-int straightforward(?) dRandInt (0..n-1)
int btSequentialImpulseConstraintSolver::btRandInt2(int n)
{
@@ -471,44 +454,42 @@ int btSequentialImpulseConstraintSolver::btRandInt2(int n)
return (int)(r % un);
}
-int btSequentialImpulseConstraintSolver::btRandInt2a(int n, unsigned long& seed)
+void btSequentialImpulseConstraintSolver::initSolverBody(btSolverBody* solverBody, btCollisionObject* collisionObject, btScalar timeStep)
{
- // seems good; xor-fold and modulus
- const unsigned long un = static_cast<unsigned long>(n);
- unsigned long r = btSequentialImpulseConstraintSolver::btRand2a(seed);
+ btRigidBody* rb = collisionObject ? btRigidBody::upcast(collisionObject) : 0;
- // note: probably more aggressive than it needs to be -- might be
- // able to get away without one or two of the innermost branches.
- if (un <= 0x00010000UL)
+ solverBody->internalGetDeltaLinearVelocity().setValue(0.f, 0.f, 0.f);
+ solverBody->internalGetDeltaAngularVelocity().setValue(0.f, 0.f, 0.f);
+ solverBody->internalGetPushVelocity().setValue(0.f, 0.f, 0.f);
+ solverBody->internalGetTurnVelocity().setValue(0.f, 0.f, 0.f);
+
+ if (rb)
{
- r ^= (r >> 16);
- if (un <= 0x00000100UL)
+ solverBody->m_worldTransform = rb->getWorldTransform();
+ solverBody->internalSetInvMass(btVector3(rb->getInvMass(), rb->getInvMass(), rb->getInvMass()) * rb->getLinearFactor());
+ solverBody->m_originalBody = rb;
+ solverBody->m_angularFactor = rb->getAngularFactor();
+ solverBody->m_linearFactor = rb->getLinearFactor();
+ solverBody->m_linearVelocity = rb->getLinearVelocity();
+ solverBody->m_angularVelocity = rb->getAngularVelocity();
+ solverBody->m_externalForceImpulse = rb->getTotalForce() * rb->getInvMass() * timeStep;
+ solverBody->m_externalTorqueImpulse = rb->getTotalTorque() * rb->getInvInertiaTensorWorld() * timeStep;
+ }
+ else
{
- r ^= (r >> 8);
- if (un <= 0x00000010UL)
- {
- r ^= (r >> 4);
- if (un <= 0x00000004UL)
- {
- r ^= (r >> 2);
- if (un <= 0x00000002UL)
- {
- r ^= (r >> 1);
+ solverBody->m_worldTransform.setIdentity();
+ solverBody->internalSetInvMass(btVector3(0, 0, 0));
+ solverBody->m_originalBody = 0;
+ solverBody->m_angularFactor.setValue(1, 1, 1);
+ solverBody->m_linearFactor.setValue(1, 1, 1);
+ solverBody->m_linearVelocity.setValue(0, 0, 0);
+ solverBody->m_angularVelocity.setValue(0, 0, 0);
+ solverBody->m_externalForceImpulse.setValue(0, 0, 0);
+ solverBody->m_externalTorqueImpulse.setValue(0, 0, 0);
}
}
- }
- }
- }
- return (int)(r % un);
-}
-
-void btSequentialImpulseConstraintSolver::initSolverBody(btSolverBody* solverBody, btCollisionObject* collisionObject, btScalar timeStep)
-{
- btSISolverSingleIterationData::initSolverBody(solverBody, collisionObject, timeStep);
-}
-
-btScalar btSequentialImpulseConstraintSolver::restitutionCurveInternal(btScalar rel_vel, btScalar restitution, btScalar velocityThreshold)
+btScalar btSequentialImpulseConstraintSolver::restitutionCurve(btScalar rel_vel, btScalar restitution, btScalar velocityThreshold)
{
//printf("rel_vel =%f\n", rel_vel);
if (btFabs(rel_vel) < velocityThreshold)
@@ -517,10 +498,6 @@ btScalar btSequentialImpulseConstraintSolver::restitutionCurveInternal(btScalar
btScalar rest = restitution * -rel_vel;
return rest;
}
-btScalar btSequentialImpulseConstraintSolver::restitutionCurve(btScalar rel_vel, btScalar restitution, btScalar velocityThreshold)
-{
- return btSequentialImpulseConstraintSolver::restitutionCurveInternal(rel_vel, restitution, velocityThreshold);
-}
void btSequentialImpulseConstraintSolver::applyAnisotropicFriction(btCollisionObject* colObj, btVector3& frictionDirection, int frictionMode)
{
@@ -536,13 +513,13 @@ void btSequentialImpulseConstraintSolver::applyAnisotropicFriction(btCollisionOb
}
}
-void btSequentialImpulseConstraintSolver::setupFrictionConstraintInternal(btAlignedObjectArray<btSolverBody>& tmpSolverBodyPool, btSolverConstraint& solverConstraint, const btVector3& normalAxis, int solverBodyIdA, int solverBodyIdB, btManifoldPoint& cp, const btVector3& rel_pos1, const btVector3& rel_pos2, btCollisionObject* colObj0, btCollisionObject* colObj1, btScalar relaxation, const btContactSolverInfo& infoGlobal, btScalar desiredVelocity, btScalar cfmSlip)
+void btSequentialImpulseConstraintSolver::setupFrictionConstraint(btSolverConstraint& solverConstraint, const btVector3& normalAxis, int solverBodyIdA, int solverBodyIdB, btManifoldPoint& cp, const btVector3& rel_pos1, const btVector3& rel_pos2, btCollisionObject* colObj0, btCollisionObject* colObj1, btScalar relaxation, const btContactSolverInfo& infoGlobal, btScalar desiredVelocity, btScalar cfmSlip)
{
- btSolverBody& solverBodyA = tmpSolverBodyPool[solverBodyIdA];
- btSolverBody& solverBodyB = tmpSolverBodyPool[solverBodyIdB];
+ btSolverBody& solverBodyA = m_tmpSolverBodyPool[solverBodyIdA];
+ btSolverBody& solverBodyB = m_tmpSolverBodyPool[solverBodyIdB];
- btRigidBody* body0 = tmpSolverBodyPool[solverBodyIdA].m_originalBody;
- btRigidBody* bodyA = tmpSolverBodyPool[solverBodyIdB].m_originalBody;
+ btRigidBody* body0 = m_tmpSolverBodyPool[solverBodyIdA].m_originalBody;
+ btRigidBody* bodyA = m_tmpSolverBodyPool[solverBodyIdB].m_originalBody;
solverConstraint.m_solverBodyIdA = solverBodyIdA;
solverConstraint.m_solverBodyIdB = solverBodyIdB;
@@ -628,22 +605,6 @@ void btSequentialImpulseConstraintSolver::setupFrictionConstraintInternal(btAlig
}
}
-void btSequentialImpulseConstraintSolver::setupFrictionConstraint(btSolverConstraint& solverConstraint, const btVector3& normalAxis, int solverBodyIdA, int solverBodyIdB, btManifoldPoint& cp, const btVector3& rel_pos1, const btVector3& rel_pos2, btCollisionObject* colObj0, btCollisionObject* colObj1, btScalar relaxation, const btContactSolverInfo& infoGlobal, btScalar desiredVelocity, btScalar cfmSlip)
-{
- btSequentialImpulseConstraintSolver::setupFrictionConstraintInternal(m_tmpSolverBodyPool, solverConstraint, normalAxis, solverBodyIdA, solverBodyIdB, cp, rel_pos1, rel_pos2, colObj0, colObj1, relaxation, infoGlobal, desiredVelocity, cfmSlip);
-}
-
-btSolverConstraint& btSequentialImpulseConstraintSolver::addFrictionConstraintInternal(btAlignedObjectArray<btSolverBody>& tmpSolverBodyPool, btConstraintArray& tmpSolverContactFrictionConstraintPool, const btVector3& normalAxis, int solverBodyIdA, int solverBodyIdB, int frictionIndex, btManifoldPoint& cp, const btVector3& rel_pos1, const btVector3& rel_pos2, btCollisionObject* colObj0, btCollisionObject* colObj1, btScalar relaxation, const btContactSolverInfo& infoGlobal, btScalar desiredVelocity, btScalar cfmSlip)
-{
- btSolverConstraint& solverConstraint = tmpSolverContactFrictionConstraintPool.expandNonInitializing();
- solverConstraint.m_frictionIndex = frictionIndex;
- setupFrictionConstraintInternal(tmpSolverBodyPool, solverConstraint, normalAxis, solverBodyIdA, solverBodyIdB, cp, rel_pos1, rel_pos2,
- colObj0, colObj1, relaxation, infoGlobal, desiredVelocity, cfmSlip);
- return solverConstraint;
-}
-
-
-
btSolverConstraint& btSequentialImpulseConstraintSolver::addFrictionConstraint(const btVector3& normalAxis, int solverBodyIdA, int solverBodyIdB, int frictionIndex, btManifoldPoint& cp, const btVector3& rel_pos1, const btVector3& rel_pos2, btCollisionObject* colObj0, btCollisionObject* colObj1, btScalar relaxation, const btContactSolverInfo& infoGlobal, btScalar desiredVelocity, btScalar cfmSlip)
{
btSolverConstraint& solverConstraint = m_tmpSolverContactFrictionConstraintPool.expandNonInitializing();
@@ -653,8 +614,7 @@ btSolverConstraint& btSequentialImpulseConstraintSolver::addFrictionConstraint(c
return solverConstraint;
}
-
-void btSequentialImpulseConstraintSolver::setupTorsionalFrictionConstraintInternal(btAlignedObjectArray<btSolverBody>& tmpSolverBodyPool, btSolverConstraint& solverConstraint, const btVector3& normalAxis1, int solverBodyIdA, int solverBodyIdB,
+void btSequentialImpulseConstraintSolver::setupTorsionalFrictionConstraint(btSolverConstraint& solverConstraint, const btVector3& normalAxis1, int solverBodyIdA, int solverBodyIdB,
btManifoldPoint& cp, btScalar combinedTorsionalFriction, const btVector3& rel_pos1, const btVector3& rel_pos2,
btCollisionObject* colObj0, btCollisionObject* colObj1, btScalar relaxation,
btScalar desiredVelocity, btScalar cfmSlip)
@@ -664,11 +624,11 @@ void btSequentialImpulseConstraintSolver::setupTorsionalFrictionConstraintIntern
solverConstraint.m_contactNormal1 = normalAxis;
solverConstraint.m_contactNormal2 = -normalAxis;
- btSolverBody& solverBodyA = tmpSolverBodyPool[solverBodyIdA];
- btSolverBody& solverBodyB = tmpSolverBodyPool[solverBodyIdB];
+ btSolverBody& solverBodyA = m_tmpSolverBodyPool[solverBodyIdA];
+ btSolverBody& solverBodyB = m_tmpSolverBodyPool[solverBodyIdB];
- btRigidBody* body0 = tmpSolverBodyPool[solverBodyIdA].m_originalBody;
- btRigidBody* bodyA = tmpSolverBodyPool[solverBodyIdB].m_originalBody;
+ btRigidBody* body0 = m_tmpSolverBodyPool[solverBodyIdA].m_originalBody;
+ btRigidBody* bodyA = m_tmpSolverBodyPool[solverBodyIdB].m_originalBody;
solverConstraint.m_solverBodyIdA = solverBodyIdA;
solverConstraint.m_solverBodyIdB = solverBodyIdB;
@@ -717,30 +677,6 @@ void btSequentialImpulseConstraintSolver::setupTorsionalFrictionConstraintIntern
}
}
-
-void btSequentialImpulseConstraintSolver::setupTorsionalFrictionConstraint(btSolverConstraint& solverConstraint, const btVector3& normalAxis1, int solverBodyIdA, int solverBodyIdB,
- btManifoldPoint& cp, btScalar combinedTorsionalFriction, const btVector3& rel_pos1, const btVector3& rel_pos2,
- btCollisionObject* colObj0, btCollisionObject* colObj1, btScalar relaxation,
- btScalar desiredVelocity, btScalar cfmSlip)
-
-{
- setupTorsionalFrictionConstraintInternal(m_tmpSolverBodyPool, solverConstraint, normalAxis1, solverBodyIdA, solverBodyIdB,
- cp, combinedTorsionalFriction, rel_pos1, rel_pos2,
- colObj0, colObj1, relaxation,
- desiredVelocity, cfmSlip);
-
-}
-
-btSolverConstraint& btSequentialImpulseConstraintSolver::addTorsionalFrictionConstraintInternal(btAlignedObjectArray<btSolverBody>& tmpSolverBodyPool, btConstraintArray& tmpSolverContactRollingFrictionConstraintPool, const btVector3& normalAxis, int solverBodyIdA, int solverBodyIdB, int frictionIndex, btManifoldPoint& cp, btScalar combinedTorsionalFriction, const btVector3& rel_pos1, const btVector3& rel_pos2, btCollisionObject* colObj0, btCollisionObject* colObj1, btScalar relaxation, btScalar desiredVelocity, btScalar cfmSlip)
-{
- btSolverConstraint& solverConstraint = tmpSolverContactRollingFrictionConstraintPool.expandNonInitializing();
- solverConstraint.m_frictionIndex = frictionIndex;
- setupTorsionalFrictionConstraintInternal(tmpSolverBodyPool, solverConstraint, normalAxis, solverBodyIdA, solverBodyIdB, cp, combinedTorsionalFriction, rel_pos1, rel_pos2,
- colObj0, colObj1, relaxation, desiredVelocity, cfmSlip);
- return solverConstraint;
-}
-
-
btSolverConstraint& btSequentialImpulseConstraintSolver::addTorsionalFrictionConstraint(const btVector3& normalAxis, int solverBodyIdA, int solverBodyIdB, int frictionIndex, btManifoldPoint& cp, btScalar combinedTorsionalFriction, const btVector3& rel_pos1, const btVector3& rel_pos2, btCollisionObject* colObj0, btCollisionObject* colObj1, btScalar relaxation, btScalar desiredVelocity, btScalar cfmSlip)
{
btSolverConstraint& solverConstraint = m_tmpSolverContactRollingFrictionConstraintPool.expandNonInitializing();
@@ -750,217 +686,6 @@ btSolverConstraint& btSequentialImpulseConstraintSolver::addTorsionalFrictionCon
return solverConstraint;
}
-int btSISolverSingleIterationData::getOrInitSolverBody(btCollisionObject & body, btScalar timeStep)
-{
-#if BT_THREADSAFE
- int solverBodyId = -1;
- bool isRigidBodyType = btRigidBody::upcast(&body) != NULL;
- if (isRigidBodyType && !body.isStaticOrKinematicObject())
- {
- // dynamic body
- // Dynamic bodies can only be in one island, so it's safe to write to the companionId
- solverBodyId = body.getCompanionId();
- if (solverBodyId < 0)
- {
- solverBodyId = m_tmpSolverBodyPool.size();
- btSolverBody& solverBody = m_tmpSolverBodyPool.expand();
- initSolverBody(&solverBody, &body, timeStep);
- body.setCompanionId(solverBodyId);
- }
- }
- else if (isRigidBodyType && body.isKinematicObject())
- {
- //
- // NOTE: must test for kinematic before static because some kinematic objects also
- // identify as "static"
- //
- // Kinematic bodies can be in multiple islands at once, so it is a
- // race condition to write to them, so we use an alternate method
- // to record the solverBodyId
- int uniqueId = body.getWorldArrayIndex();
- const int INVALID_SOLVER_BODY_ID = -1;
- if (uniqueId >= m_kinematicBodyUniqueIdToSolverBodyTable.size())
- {
- m_kinematicBodyUniqueIdToSolverBodyTable.resize(uniqueId + 1, INVALID_SOLVER_BODY_ID);
- }
- solverBodyId = m_kinematicBodyUniqueIdToSolverBodyTable[uniqueId];
- // if no table entry yet,
- if (solverBodyId == INVALID_SOLVER_BODY_ID)
- {
- // create a table entry for this body
- solverBodyId = m_tmpSolverBodyPool.size();
- btSolverBody& solverBody = m_tmpSolverBodyPool.expand();
- initSolverBody(&solverBody, &body, timeStep);
- m_kinematicBodyUniqueIdToSolverBodyTable[uniqueId] = solverBodyId;
- }
- }
- else
- {
- bool isMultiBodyType = (body.getInternalType() & btCollisionObject::CO_FEATHERSTONE_LINK);
- // Incorrectly set collision object flags can degrade performance in various ways.
- if (!isMultiBodyType)
- {
- btAssert(body.isStaticOrKinematicObject());
- }
- //it could be a multibody link collider
- // all fixed bodies (inf mass) get mapped to a single solver id
- if (m_fixedBodyId < 0)
- {
- m_fixedBodyId = m_tmpSolverBodyPool.size();
- btSolverBody& fixedBody = m_tmpSolverBodyPool.expand();
- initSolverBody(&fixedBody, 0, timeStep);
- }
- solverBodyId = m_fixedBodyId;
- }
- btAssert(solverBodyId >= 0 && solverBodyId < m_tmpSolverBodyPool.size());
- return solverBodyId;
-#else // BT_THREADSAFE
-
- int solverBodyIdA = -1;
-
- if (body.getCompanionId() >= 0)
- {
- //body has already been converted
- solverBodyIdA = body.getCompanionId();
- btAssert(solverBodyIdA < m_tmpSolverBodyPool.size());
- }
- else
- {
- btRigidBody* rb = btRigidBody::upcast(&body);
- //convert both active and kinematic objects (for their velocity)
- if (rb && (rb->getInvMass() || rb->isKinematicObject()))
- {
- solverBodyIdA = m_tmpSolverBodyPool.size();
- btSolverBody& solverBody = m_tmpSolverBodyPool.expand();
- initSolverBody(&solverBody, &body, timeStep);
- body.setCompanionId(solverBodyIdA);
- }
- else
- {
- if (m_fixedBodyId < 0)
- {
- m_fixedBodyId = m_tmpSolverBodyPool.size();
- btSolverBody& fixedBody = m_tmpSolverBodyPool.expand();
- initSolverBody(&fixedBody, 0, timeStep);
- }
- return m_fixedBodyId;
- // return 0;//assume first one is a fixed solver body
- }
- }
-
- return solverBodyIdA;
-#endif // BT_THREADSAFE
-}
-void btSISolverSingleIterationData::initSolverBody(btSolverBody * solverBody, btCollisionObject * collisionObject, btScalar timeStep)
-{
- btRigidBody* rb = collisionObject ? btRigidBody::upcast(collisionObject) : 0;
-
- solverBody->internalGetDeltaLinearVelocity().setValue(0.f, 0.f, 0.f);
- solverBody->internalGetDeltaAngularVelocity().setValue(0.f, 0.f, 0.f);
- solverBody->internalGetPushVelocity().setValue(0.f, 0.f, 0.f);
- solverBody->internalGetTurnVelocity().setValue(0.f, 0.f, 0.f);
-
- if (rb)
- {
- solverBody->m_worldTransform = rb->getWorldTransform();
- solverBody->internalSetInvMass(btVector3(rb->getInvMass(), rb->getInvMass(), rb->getInvMass()) * rb->getLinearFactor());
- solverBody->m_originalBody = rb;
- solverBody->m_angularFactor = rb->getAngularFactor();
- solverBody->m_linearFactor = rb->getLinearFactor();
- solverBody->m_linearVelocity = rb->getLinearVelocity();
- solverBody->m_angularVelocity = rb->getAngularVelocity();
- solverBody->m_externalForceImpulse = rb->getTotalForce() * rb->getInvMass() * timeStep;
- solverBody->m_externalTorqueImpulse = rb->getTotalTorque() * rb->getInvInertiaTensorWorld() * timeStep;
- }
- else
- {
- solverBody->m_worldTransform.setIdentity();
- solverBody->internalSetInvMass(btVector3(0, 0, 0));
- solverBody->m_originalBody = 0;
- solverBody->m_angularFactor.setValue(1, 1, 1);
- solverBody->m_linearFactor.setValue(1, 1, 1);
- solverBody->m_linearVelocity.setValue(0, 0, 0);
- solverBody->m_angularVelocity.setValue(0, 0, 0);
- solverBody->m_externalForceImpulse.setValue(0, 0, 0);
- solverBody->m_externalTorqueImpulse.setValue(0, 0, 0);
- }
-}
-
-int btSISolverSingleIterationData::getSolverBody(btCollisionObject& body) const
-{
-#if BT_THREADSAFE
- int solverBodyId = -1;
- bool isRigidBodyType = btRigidBody::upcast(&body) != NULL;
- if (isRigidBodyType && !body.isStaticOrKinematicObject())
- {
- // dynamic body
- // Dynamic bodies can only be in one island, so it's safe to write to the companionId
- solverBodyId = body.getCompanionId();
- btAssert(solverBodyId >= 0);
- }
- else if (isRigidBodyType && body.isKinematicObject())
- {
- //
- // NOTE: must test for kinematic before static because some kinematic objects also
- // identify as "static"
- //
- // Kinematic bodies can be in multiple islands at once, so it is a
- // race condition to write to them, so we use an alternate method
- // to record the solverBodyId
- int uniqueId = body.getWorldArrayIndex();
- const int INVALID_SOLVER_BODY_ID = -1;
- if (uniqueId >= m_kinematicBodyUniqueIdToSolverBodyTable.size())
- {
- m_kinematicBodyUniqueIdToSolverBodyTable.resize(uniqueId + 1, INVALID_SOLVER_BODY_ID);
- }
- solverBodyId = m_kinematicBodyUniqueIdToSolverBodyTable[uniqueId];
- btAssert(solverBodyId != INVALID_SOLVER_BODY_ID);
- }
- else
- {
- bool isMultiBodyType = (body.getInternalType() & btCollisionObject::CO_FEATHERSTONE_LINK);
- // Incorrectly set collision object flags can degrade performance in various ways.
- if (!isMultiBodyType)
- {
- btAssert(body.isStaticOrKinematicObject());
- }
- btAssert(m_fixedBodyId >= 0);
- solverBodyId = m_fixedBodyId;
- }
- btAssert(solverBodyId >= 0 && solverBodyId < m_tmpSolverBodyPool.size());
- return solverBodyId;
-#else // BT_THREADSAFE
- int solverBodyIdA = -1;
-
- if (body.getCompanionId() >= 0)
- {
- //body has already been converted
- solverBodyIdA = body.getCompanionId();
- btAssert(solverBodyIdA < m_tmpSolverBodyPool.size());
- }
- else
- {
- btRigidBody* rb = btRigidBody::upcast(&body);
- //convert both active and kinematic objects (for their velocity)
- if (rb && (rb->getInvMass() || rb->isKinematicObject()))
- {
- btAssert(0);
- }
- else
- {
- if (m_fixedBodyId < 0)
- {
- btAssert(0);
- }
- return m_fixedBodyId;
- // return 0;//assume first one is a fixed solver body
- }
- }
-
- return solverBodyIdA;
-#endif // BT_THREADSAFE
-}
-
int btSequentialImpulseConstraintSolver::getOrInitSolverBody(btCollisionObject& body, btScalar timeStep)
{
#if BT_THREADSAFE
@@ -1064,10 +789,7 @@ int btSequentialImpulseConstraintSolver::getOrInitSolverBody(btCollisionObject&
}
#include <stdio.h>
-
-
-void btSequentialImpulseConstraintSolver::setupContactConstraintInternal(btSISolverSingleIterationData& siData,
- btSolverConstraint& solverConstraint,
+void btSequentialImpulseConstraintSolver::setupContactConstraint(btSolverConstraint& solverConstraint,
int solverBodyIdA, int solverBodyIdB,
btManifoldPoint& cp, const btContactSolverInfo& infoGlobal,
btScalar& relaxation,
@@ -1076,8 +798,8 @@ void btSequentialImpulseConstraintSolver::setupContactConstraintInternal(btSISol
// const btVector3& pos1 = cp.getPositionWorldOnA();
// const btVector3& pos2 = cp.getPositionWorldOnB();
- btSolverBody* bodyA = &siData.m_tmpSolverBodyPool[solverBodyIdA];
- btSolverBody* bodyB = &siData.m_tmpSolverBodyPool[solverBodyIdB];
+ btSolverBody* bodyA = &m_tmpSolverBodyPool[solverBodyIdA];
+ btSolverBody* bodyB = &m_tmpSolverBodyPool[solverBodyIdB];
btRigidBody* rb0 = bodyA->m_originalBody;
btRigidBody* rb1 = bodyB->m_originalBody;
@@ -1184,7 +906,7 @@ void btSequentialImpulseConstraintSolver::setupContactConstraintInternal(btSISol
solverConstraint.m_friction = cp.m_combinedFriction;
- restitution = btSequentialImpulseConstraintSolver::restitutionCurveInternal(rel_vel, cp.m_combinedRestitution, infoGlobal.m_restitutionVelocityThreshold);
+ restitution = restitutionCurve(rel_vel, cp.m_combinedRestitution, infoGlobal.m_restitutionVelocityThreshold);
if (restitution <= btScalar(0.))
{
restitution = 0.f;
@@ -1252,109 +974,39 @@ void btSequentialImpulseConstraintSolver::setupContactConstraintInternal(btSISol
}
}
-void btSequentialImpulseConstraintSolver::setupContactConstraint(btSolverConstraint& solverConstraint,
- int solverBodyIdA, int solverBodyIdB,
- btManifoldPoint& cp, const btContactSolverInfo& infoGlobal,
- btScalar& relaxation,
- const btVector3& rel_pos1, const btVector3& rel_pos2)
-{
- btSISolverSingleIterationData siData(m_tmpSolverBodyPool,
- m_tmpSolverContactConstraintPool,
- m_tmpSolverNonContactConstraintPool,
- m_tmpSolverContactFrictionConstraintPool,
- m_tmpSolverContactRollingFrictionConstraintPool,
- m_orderTmpConstraintPool,
- m_orderNonContactConstraintPool,
- m_orderFrictionConstraintPool,
- m_tmpConstraintSizesPool,
- m_resolveSingleConstraintRowGeneric,
- m_resolveSingleConstraintRowLowerLimit,
- m_resolveSplitPenetrationImpulse,
- m_kinematicBodyUniqueIdToSolverBodyTable,
- m_btSeed2,
- m_fixedBodyId,
- m_maxOverrideNumSolverIterations
- );
-
-
- setupContactConstraintInternal(siData, solverConstraint,
- solverBodyIdA, solverBodyIdB,
- cp, infoGlobal,
- relaxation,
- rel_pos1, rel_pos2);
-}
-
-
-void btSequentialImpulseConstraintSolver::setFrictionConstraintImpulseInternal(btAlignedObjectArray<btSolverBody>& tmpSolverBodyPool, btConstraintArray& tmpSolverContactFrictionConstraintPool,
- btSolverConstraint& solverConstraint,
+void btSequentialImpulseConstraintSolver::setFrictionConstraintImpulse(btSolverConstraint& solverConstraint,
int solverBodyIdA, int solverBodyIdB,
btManifoldPoint& cp, const btContactSolverInfo& infoGlobal)
{
- btSolverBody* bodyA = &tmpSolverBodyPool[solverBodyIdA];
- btSolverBody* bodyB = &tmpSolverBodyPool[solverBodyIdB];
-
- btRigidBody* rb0 = bodyA->m_originalBody;
- btRigidBody* rb1 = bodyB->m_originalBody;
-
{
- btSolverConstraint& frictionConstraint1 = tmpSolverContactFrictionConstraintPool[solverConstraint.m_frictionIndex];
- if (infoGlobal.m_solverMode & SOLVER_USE_WARMSTARTING)
- {
- frictionConstraint1.m_appliedImpulse = cp.m_appliedImpulseLateral1 * infoGlobal.m_warmstartingFactor;
- if (rb0)
- bodyA->internalApplyImpulse(frictionConstraint1.m_contactNormal1 * rb0->getInvMass(), frictionConstraint1.m_angularComponentA, frictionConstraint1.m_appliedImpulse);
- if (rb1)
- bodyB->internalApplyImpulse(-frictionConstraint1.m_contactNormal2 * rb1->getInvMass(), -frictionConstraint1.m_angularComponentB, -(btScalar)frictionConstraint1.m_appliedImpulse);
- }
- else
- {
- frictionConstraint1.m_appliedImpulse = 0.f;
- }
+ btSolverConstraint& frictionConstraint1 = m_tmpSolverContactFrictionConstraintPool[solverConstraint.m_frictionIndex];
+
+ frictionConstraint1.m_appliedImpulse = 0.f;
}
if ((infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS))
{
- btSolverConstraint& frictionConstraint2 = tmpSolverContactFrictionConstraintPool[solverConstraint.m_frictionIndex + 1];
- if (infoGlobal.m_solverMode & SOLVER_USE_WARMSTARTING)
- {
- frictionConstraint2.m_appliedImpulse = cp.m_appliedImpulseLateral2 * infoGlobal.m_warmstartingFactor;
- if (rb0)
- bodyA->internalApplyImpulse(frictionConstraint2.m_contactNormal1 * rb0->getInvMass(), frictionConstraint2.m_angularComponentA, frictionConstraint2.m_appliedImpulse);
- if (rb1)
- bodyB->internalApplyImpulse(-frictionConstraint2.m_contactNormal2 * rb1->getInvMass(), -frictionConstraint2.m_angularComponentB, -(btScalar)frictionConstraint2.m_appliedImpulse);
- }
- else
- {
- frictionConstraint2.m_appliedImpulse = 0.f;
- }
+ btSolverConstraint& frictionConstraint2 = m_tmpSolverContactFrictionConstraintPool[solverConstraint.m_frictionIndex + 1];
+
+ frictionConstraint2.m_appliedImpulse = 0.f;
}
}
-void btSequentialImpulseConstraintSolver::setFrictionConstraintImpulse(btSolverConstraint& solverConstraint,
- int solverBodyIdA, int solverBodyIdB,
- btManifoldPoint& cp, const btContactSolverInfo& infoGlobal)
-{
- setFrictionConstraintImpulseInternal(m_tmpSolverBodyPool, m_tmpSolverContactFrictionConstraintPool,
- solverConstraint,
- solverBodyIdA, solverBodyIdB,
- cp, infoGlobal);
-
-}
-void btSequentialImpulseConstraintSolver::convertContactInternal(btSISolverSingleIterationData& siData, btPersistentManifold* manifold, const btContactSolverInfo& infoGlobal)
+void btSequentialImpulseConstraintSolver::convertContact(btPersistentManifold* manifold, const btContactSolverInfo& infoGlobal)
{
btCollisionObject *colObj0 = 0, *colObj1 = 0;
colObj0 = (btCollisionObject*)manifold->getBody0();
colObj1 = (btCollisionObject*)manifold->getBody1();
- int solverBodyIdA = siData.getOrInitSolverBody(*colObj0, infoGlobal.m_timeStep);
- int solverBodyIdB = siData.getOrInitSolverBody(*colObj1, infoGlobal.m_timeStep);
+ int solverBodyIdA = getOrInitSolverBody(*colObj0, infoGlobal.m_timeStep);
+ int solverBodyIdB = getOrInitSolverBody(*colObj1, infoGlobal.m_timeStep);
// btRigidBody* bodyA = btRigidBody::upcast(colObj0);
// btRigidBody* bodyB = btRigidBody::upcast(colObj1);
- btSolverBody* solverBodyA = &siData.m_tmpSolverBodyPool[solverBodyIdA];
- btSolverBody* solverBodyB = &siData.m_tmpSolverBodyPool[solverBodyIdB];
+ btSolverBody* solverBodyA = &m_tmpSolverBodyPool[solverBodyIdA];
+ btSolverBody* solverBodyB = &m_tmpSolverBodyPool[solverBodyIdB];
///avoid collision response between two static objects
if (!solverBodyA || (solverBodyA->m_invMass.fuzzyZero() && (!solverBodyB || solverBodyB->m_invMass.fuzzyZero())))
@@ -1371,8 +1023,8 @@ void btSequentialImpulseConstraintSolver::convertContactInternal(btSISolverSingl
btVector3 rel_pos2;
btScalar relaxation;
- int frictionIndex = siData.m_tmpSolverContactConstraintPool.size();
- btSolverConstraint& solverConstraint = siData.m_tmpSolverContactConstraintPool.expandNonInitializing();
+ int frictionIndex = m_tmpSolverContactConstraintPool.size();
+ btSolverConstraint& solverConstraint = m_tmpSolverContactConstraintPool.expandNonInitializing();
solverConstraint.m_solverBodyIdA = solverBodyIdA;
solverConstraint.m_solverBodyIdB = solverBodyIdB;
@@ -1393,20 +1045,16 @@ void btSequentialImpulseConstraintSolver::convertContactInternal(btSISolverSingl
btVector3 vel = vel1 - vel2;
btScalar rel_vel = cp.m_normalWorldOnB.dot(vel);
- setupContactConstraintInternal(siData, solverConstraint, solverBodyIdA, solverBodyIdB, cp, infoGlobal, relaxation, rel_pos1, rel_pos2);
+ setupContactConstraint(solverConstraint, solverBodyIdA, solverBodyIdB, cp, infoGlobal, relaxation, rel_pos1, rel_pos2);
/////setup the friction constraints
- solverConstraint.m_frictionIndex = siData.m_tmpSolverContactFrictionConstraintPool.size();
+ solverConstraint.m_frictionIndex = m_tmpSolverContactFrictionConstraintPool.size();
if ((cp.m_combinedRollingFriction > 0.f) && (rollingFriction > 0))
{
{
-
- btSequentialImpulseConstraintSolver::addTorsionalFrictionConstraintInternal(siData.m_tmpSolverBodyPool,
- siData.m_tmpSolverContactRollingFrictionConstraintPool,
- cp.m_normalWorldOnB, solverBodyIdA, solverBodyIdB, frictionIndex, cp, cp.m_combinedSpinningFriction, rel_pos1, rel_pos2, colObj0, colObj1, relaxation);
-
+ addTorsionalFrictionConstraint(cp.m_normalWorldOnB, solverBodyIdA, solverBodyIdB, frictionIndex, cp, cp.m_combinedSpinningFriction, rel_pos1, rel_pos2, colObj0, colObj1, relaxation);
btVector3 axis0, axis1;
btPlaneSpace1(cp.m_normalWorldOnB, axis0, axis1);
axis0.normalize();
@@ -1417,19 +1065,13 @@ void btSequentialImpulseConstraintSolver::convertContactInternal(btSISolverSingl
applyAnisotropicFriction(colObj0, axis1, btCollisionObject::CF_ANISOTROPIC_ROLLING_FRICTION);
applyAnisotropicFriction(colObj1, axis1, btCollisionObject::CF_ANISOTROPIC_ROLLING_FRICTION);
if (axis0.length() > 0.001)
- {
- btSequentialImpulseConstraintSolver::addTorsionalFrictionConstraintInternal(siData.m_tmpSolverBodyPool,
- siData.m_tmpSolverContactRollingFrictionConstraintPool, axis0, solverBodyIdA, solverBodyIdB, frictionIndex, cp,
+ addTorsionalFrictionConstraint(axis0, solverBodyIdA, solverBodyIdB, frictionIndex, cp,
cp.m_combinedRollingFriction, rel_pos1, rel_pos2, colObj0, colObj1, relaxation);
- }
if (axis1.length() > 0.001)
- {
- btSequentialImpulseConstraintSolver::addTorsionalFrictionConstraintInternal(siData.m_tmpSolverBodyPool,
- siData.m_tmpSolverContactRollingFrictionConstraintPool, axis1, solverBodyIdA, solverBodyIdB, frictionIndex, cp,
+ addTorsionalFrictionConstraint(axis1, solverBodyIdA, solverBodyIdB, frictionIndex, cp,
cp.m_combinedRollingFriction, rel_pos1, rel_pos2, colObj0, colObj1, relaxation);
}
}
- }
///Bullet has several options to set the friction directions
///By default, each contact has only a single friction direction that is recomputed automatically very frame
@@ -1456,8 +1098,7 @@ void btSequentialImpulseConstraintSolver::convertContactInternal(btSISolverSingl
cp.m_lateralFrictionDir1 *= 1.f / btSqrt(lat_rel_vel);
applyAnisotropicFriction(colObj0, cp.m_lateralFrictionDir1, btCollisionObject::CF_ANISOTROPIC_FRICTION);
applyAnisotropicFriction(colObj1, cp.m_lateralFrictionDir1, btCollisionObject::CF_ANISOTROPIC_FRICTION);
- btSequentialImpulseConstraintSolver::addFrictionConstraintInternal(siData.m_tmpSolverBodyPool, siData.m_tmpSolverContactFrictionConstraintPool,
- cp.m_lateralFrictionDir1, solverBodyIdA, solverBodyIdB, frictionIndex, cp, rel_pos1, rel_pos2, colObj0, colObj1, relaxation, infoGlobal);
+ addFrictionConstraint(cp.m_lateralFrictionDir1, solverBodyIdA, solverBodyIdB, frictionIndex, cp, rel_pos1, rel_pos2, colObj0, colObj1, relaxation, infoGlobal);
if ((infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS))
{
@@ -1465,8 +1106,7 @@ void btSequentialImpulseConstraintSolver::convertContactInternal(btSISolverSingl
cp.m_lateralFrictionDir2.normalize(); //??
applyAnisotropicFriction(colObj0, cp.m_lateralFrictionDir2, btCollisionObject::CF_ANISOTROPIC_FRICTION);
applyAnisotropicFriction(colObj1, cp.m_lateralFrictionDir2, btCollisionObject::CF_ANISOTROPIC_FRICTION);
- btSequentialImpulseConstraintSolver::addFrictionConstraintInternal(siData.m_tmpSolverBodyPool, siData.m_tmpSolverContactFrictionConstraintPool,
- cp.m_lateralFrictionDir2, solverBodyIdA, solverBodyIdB, frictionIndex, cp, rel_pos1, rel_pos2, colObj0, colObj1, relaxation, infoGlobal);
+ addFrictionConstraint(cp.m_lateralFrictionDir2, solverBodyIdA, solverBodyIdB, frictionIndex, cp, rel_pos1, rel_pos2, colObj0, colObj1, relaxation, infoGlobal);
}
}
else
@@ -1475,15 +1115,13 @@ void btSequentialImpulseConstraintSolver::convertContactInternal(btSISolverSingl
applyAnisotropicFriction(colObj0, cp.m_lateralFrictionDir1, btCollisionObject::CF_ANISOTROPIC_FRICTION);
applyAnisotropicFriction(colObj1, cp.m_lateralFrictionDir1, btCollisionObject::CF_ANISOTROPIC_FRICTION);
- btSequentialImpulseConstraintSolver::addFrictionConstraintInternal(siData.m_tmpSolverBodyPool, siData.m_tmpSolverContactFrictionConstraintPool,
- cp.m_lateralFrictionDir1, solverBodyIdA, solverBodyIdB, frictionIndex, cp, rel_pos1, rel_pos2, colObj0, colObj1, relaxation, infoGlobal);
+ addFrictionConstraint(cp.m_lateralFrictionDir1, solverBodyIdA, solverBodyIdB, frictionIndex, cp, rel_pos1, rel_pos2, colObj0, colObj1, relaxation, infoGlobal);
if ((infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS))
{
applyAnisotropicFriction(colObj0, cp.m_lateralFrictionDir2, btCollisionObject::CF_ANISOTROPIC_FRICTION);
applyAnisotropicFriction(colObj1, cp.m_lateralFrictionDir2, btCollisionObject::CF_ANISOTROPIC_FRICTION);
- btSequentialImpulseConstraintSolver::addFrictionConstraintInternal(siData.m_tmpSolverBodyPool, siData.m_tmpSolverContactFrictionConstraintPool,
- cp.m_lateralFrictionDir2, solverBodyIdA, solverBodyIdB, frictionIndex, cp, rel_pos1, rel_pos2, colObj0, colObj1, relaxation, infoGlobal);
+ addFrictionConstraint(cp.m_lateralFrictionDir2, solverBodyIdA, solverBodyIdB, frictionIndex, cp, rel_pos1, rel_pos2, colObj0, colObj1, relaxation, infoGlobal);
}
if ((infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS) && (infoGlobal.m_solverMode & SOLVER_DISABLE_VELOCITY_DEPENDENT_FRICTION_DIRECTION))
@@ -1494,43 +1132,15 @@ void btSequentialImpulseConstraintSolver::convertContactInternal(btSISolverSingl
}
else
{
- btSequentialImpulseConstraintSolver::addFrictionConstraintInternal(siData.m_tmpSolverBodyPool, siData.m_tmpSolverContactFrictionConstraintPool,
- cp.m_lateralFrictionDir1, solverBodyIdA, solverBodyIdB, frictionIndex, cp, rel_pos1, rel_pos2, colObj0, colObj1, relaxation, infoGlobal, cp.m_contactMotion1, cp.m_frictionCFM);
+ addFrictionConstraint(cp.m_lateralFrictionDir1, solverBodyIdA, solverBodyIdB, frictionIndex, cp, rel_pos1, rel_pos2, colObj0, colObj1, relaxation, infoGlobal, cp.m_contactMotion1, cp.m_frictionCFM);
if ((infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS))
- {
- btSequentialImpulseConstraintSolver::addFrictionConstraintInternal(siData.m_tmpSolverBodyPool, siData.m_tmpSolverContactFrictionConstraintPool,
- cp.m_lateralFrictionDir2, solverBodyIdA, solverBodyIdB, frictionIndex, cp, rel_pos1, rel_pos2, colObj0, colObj1, relaxation, infoGlobal, cp.m_contactMotion2, cp.m_frictionCFM);
+ addFrictionConstraint(cp.m_lateralFrictionDir2, solverBodyIdA, solverBodyIdB, frictionIndex, cp, rel_pos1, rel_pos2, colObj0, colObj1, relaxation, infoGlobal, cp.m_contactMotion2, cp.m_frictionCFM);
}
+ setFrictionConstraintImpulse(solverConstraint, solverBodyIdA, solverBodyIdB, cp, infoGlobal);
}
- btSequentialImpulseConstraintSolver::setFrictionConstraintImpulseInternal(
- siData.m_tmpSolverBodyPool, siData.m_tmpSolverContactFrictionConstraintPool,
- solverConstraint, solverBodyIdA, solverBodyIdB, cp, infoGlobal);
}
}
-}
-
-void btSequentialImpulseConstraintSolver::convertContact(btPersistentManifold* manifold, const btContactSolverInfo& infoGlobal)
-{
- btSISolverSingleIterationData siData(m_tmpSolverBodyPool,
- m_tmpSolverContactConstraintPool,
- m_tmpSolverNonContactConstraintPool,
- m_tmpSolverContactFrictionConstraintPool,
- m_tmpSolverContactRollingFrictionConstraintPool,
- m_orderTmpConstraintPool,
- m_orderNonContactConstraintPool,
- m_orderFrictionConstraintPool,
- m_tmpConstraintSizesPool,
- m_resolveSingleConstraintRowGeneric,
- m_resolveSingleConstraintRowLowerLimit,
- m_resolveSplitPenetrationImpulse,
- m_kinematicBodyUniqueIdToSolverBodyTable,
- m_btSeed2,
- m_fixedBodyId,
- m_maxOverrideNumSolverIterations);
-
- btSequentialImpulseConstraintSolver::convertContactInternal(siData, manifold, infoGlobal);
-}
void btSequentialImpulseConstraintSolver::convertContacts(btPersistentManifold** manifoldPtr, int numManifolds, const btContactSolverInfo& infoGlobal)
{
@@ -1545,9 +1155,7 @@ void btSequentialImpulseConstraintSolver::convertContacts(btPersistentManifold**
}
}
-void btSequentialImpulseConstraintSolver::convertJointInternal(btAlignedObjectArray<btSolverBody>& tmpSolverBodyPool,
- int& maxOverrideNumSolverIterations,
- btSolverConstraint* currentConstraintRow,
+void btSequentialImpulseConstraintSolver::convertJoint(btSolverConstraint* currentConstraintRow,
btTypedConstraint* constraint,
const btTypedConstraint::btConstraintInfo1& info1,
int solverBodyIdA,
@@ -1557,12 +1165,12 @@ void btSequentialImpulseConstraintSolver::convertJointInternal(btAlignedObjectAr
const btRigidBody& rbA = constraint->getRigidBodyA();
const btRigidBody& rbB = constraint->getRigidBodyB();
- const btSolverBody* bodyAPtr = &tmpSolverBodyPool[solverBodyIdA];
- const btSolverBody* bodyBPtr = &tmpSolverBodyPool[solverBodyIdB];
+ const btSolverBody* bodyAPtr = &m_tmpSolverBodyPool[solverBodyIdA];
+ const btSolverBody* bodyBPtr = &m_tmpSolverBodyPool[solverBodyIdB];
int overrideNumSolverIterations = constraint->getOverrideNumSolverIterations() > 0 ? constraint->getOverrideNumSolverIterations() : infoGlobal.m_numIterations;
- if (overrideNumSolverIterations > maxOverrideNumSolverIterations)
- maxOverrideNumSolverIterations = overrideNumSolverIterations;
+ if (overrideNumSolverIterations > m_maxOverrideNumSolverIterations)
+ m_maxOverrideNumSolverIterations = overrideNumSolverIterations;
for (int j = 0; j < info1.m_numConstraintRows; j++)
{
@@ -1679,16 +1287,7 @@ void btSequentialImpulseConstraintSolver::convertJointInternal(btAlignedObjectAr
}
}
-void btSequentialImpulseConstraintSolver::convertJoint(btSolverConstraint* currentConstraintRow,
- btTypedConstraint* constraint,
- const btTypedConstraint::btConstraintInfo1& info1,
- int solverBodyIdA,
- int solverBodyIdB,
- const btContactSolverInfo& infoGlobal)
-{
-}
-
-void btSequentialImpulseConstraintSolver::convertJointsInternal(btSISolverSingleIterationData& siData, btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& infoGlobal)
+void btSequentialImpulseConstraintSolver::convertJoints(btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& infoGlobal)
{
BT_PROFILE("convertJoints");
for (int j = 0; j < numConstraints; j++)
@@ -1700,11 +1299,11 @@ void btSequentialImpulseConstraintSolver::convertJointsInternal(btSISolverSingle
int totalNumRows = 0;
- siData.m_tmpConstraintSizesPool.resizeNoInitialize(numConstraints);
+ m_tmpConstraintSizesPool.resizeNoInitialize(numConstraints);
//calculate the total number of contraint rows
for (int i = 0; i < numConstraints; i++)
{
- btTypedConstraint::btConstraintInfo1& info1 = siData.m_tmpConstraintSizesPool[i];
+ btTypedConstraint::btConstraintInfo1& info1 = m_tmpConstraintSizesPool[i];
btJointFeedback* fb = constraints[i]->getJointFeedback();
if (fb)
{
@@ -1725,58 +1324,34 @@ void btSequentialImpulseConstraintSolver::convertJointsInternal(btSISolverSingle
}
totalNumRows += info1.m_numConstraintRows;
}
- siData.m_tmpSolverNonContactConstraintPool.resizeNoInitialize(totalNumRows);
+ m_tmpSolverNonContactConstraintPool.resizeNoInitialize(totalNumRows);
///setup the btSolverConstraints
int currentRow = 0;
for (int i = 0; i < numConstraints; i++)
{
- const btTypedConstraint::btConstraintInfo1& info1 = siData.m_tmpConstraintSizesPool[i];
+ const btTypedConstraint::btConstraintInfo1& info1 = m_tmpConstraintSizesPool[i];
if (info1.m_numConstraintRows)
{
btAssert(currentRow < totalNumRows);
- btSolverConstraint* currentConstraintRow = &siData.m_tmpSolverNonContactConstraintPool[currentRow];
+ btSolverConstraint* currentConstraintRow = &m_tmpSolverNonContactConstraintPool[currentRow];
btTypedConstraint* constraint = constraints[i];
btRigidBody& rbA = constraint->getRigidBodyA();
btRigidBody& rbB = constraint->getRigidBodyB();
- int solverBodyIdA = siData.getOrInitSolverBody(rbA, infoGlobal.m_timeStep);
- int solverBodyIdB = siData.getOrInitSolverBody(rbB, infoGlobal.m_timeStep);
+ int solverBodyIdA = getOrInitSolverBody(rbA, infoGlobal.m_timeStep);
+ int solverBodyIdB = getOrInitSolverBody(rbB, infoGlobal.m_timeStep);
- convertJointInternal(siData.m_tmpSolverBodyPool, siData.m_maxOverrideNumSolverIterations,
- currentConstraintRow, constraint, info1, solverBodyIdA, solverBodyIdB, infoGlobal);
+ convertJoint(currentConstraintRow, constraint, info1, solverBodyIdA, solverBodyIdB, infoGlobal);
}
currentRow += info1.m_numConstraintRows;
}
}
-void btSequentialImpulseConstraintSolver::convertJoints(btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& infoGlobal)
-{
- btSISolverSingleIterationData siData(m_tmpSolverBodyPool,
- m_tmpSolverContactConstraintPool,
- m_tmpSolverNonContactConstraintPool,
- m_tmpSolverContactFrictionConstraintPool,
- m_tmpSolverContactRollingFrictionConstraintPool,
- m_orderTmpConstraintPool,
- m_orderNonContactConstraintPool,
- m_orderFrictionConstraintPool,
- m_tmpConstraintSizesPool,
- m_resolveSingleConstraintRowGeneric,
- m_resolveSingleConstraintRowLowerLimit,
- m_resolveSplitPenetrationImpulse,
- m_kinematicBodyUniqueIdToSolverBodyTable,
- m_btSeed2,
- m_fixedBodyId,
- m_maxOverrideNumSolverIterations);
-
- convertJointsInternal(siData, constraints, numConstraints, infoGlobal);
-}
-
-
-void btSequentialImpulseConstraintSolver::convertBodiesInternal(btSISolverSingleIterationData& siData, btCollisionObject** bodies, int numBodies, const btContactSolverInfo& infoGlobal)
+void btSequentialImpulseConstraintSolver::convertBodies(btCollisionObject** bodies, int numBodies, const btContactSolverInfo& infoGlobal)
{
BT_PROFILE("convertBodies");
for (int i = 0; i < numBodies; i++)
@@ -1784,23 +1359,23 @@ void btSequentialImpulseConstraintSolver::convertBodiesInternal(btSISolverSingle
bodies[i]->setCompanionId(-1);
}
#if BT_THREADSAFE
- siData.m_kinematicBodyUniqueIdToSolverBodyTable.resize(0);
+ m_kinematicBodyUniqueIdToSolverBodyTable.resize(0);
#endif // BT_THREADSAFE
- siData.m_tmpSolverBodyPool.reserve(numBodies + 1);
- siData.m_tmpSolverBodyPool.resize(0);
+ m_tmpSolverBodyPool.reserve(numBodies + 1);
+ m_tmpSolverBodyPool.resize(0);
//btSolverBody& fixedBody = m_tmpSolverBodyPool.expand();
//initSolverBody(&fixedBody,0);
for (int i = 0; i < numBodies; i++)
{
- int bodyId = siData.getOrInitSolverBody(*bodies[i], infoGlobal.m_timeStep);
+ int bodyId = getOrInitSolverBody(*bodies[i], infoGlobal.m_timeStep);
btRigidBody* body = btRigidBody::upcast(bodies[i]);
if (body && body->getInvMass())
{
- btSolverBody& solverBody = siData.m_tmpSolverBodyPool[bodyId];
+ btSolverBody& solverBody = m_tmpSolverBodyPool[bodyId];
btVector3 gyroForce(0, 0, 0);
if (body->getFlags() & BT_ENABLE_GYROSCOPIC_FORCE_EXPLICIT)
{
@@ -1821,29 +1396,6 @@ void btSequentialImpulseConstraintSolver::convertBodiesInternal(btSISolverSingle
}
}
-
-void btSequentialImpulseConstraintSolver::convertBodies(btCollisionObject** bodies, int numBodies, const btContactSolverInfo& infoGlobal)
-{
- btSISolverSingleIterationData siData(m_tmpSolverBodyPool,
- m_tmpSolverContactConstraintPool,
- m_tmpSolverNonContactConstraintPool,
- m_tmpSolverContactFrictionConstraintPool,
- m_tmpSolverContactRollingFrictionConstraintPool,
- m_orderTmpConstraintPool,
- m_orderNonContactConstraintPool,
- m_orderFrictionConstraintPool,
- m_tmpConstraintSizesPool,
- m_resolveSingleConstraintRowGeneric,
- m_resolveSingleConstraintRowLowerLimit,
- m_resolveSplitPenetrationImpulse,
- m_kinematicBodyUniqueIdToSolverBodyTable,
- m_btSeed2,
- m_fixedBodyId,
- m_maxOverrideNumSolverIterations);
-
- convertBodiesInternal(siData, bodies, numBodies, infoGlobal);
-}
-
btScalar btSequentialImpulseConstraintSolver::solveGroupCacheFriendlySetup(btCollisionObject** bodies, int numBodies, btPersistentManifold** manifoldPtr, int numManifolds, btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& infoGlobal, btIDebugDraw* debugDrawer)
{
m_fixedBodyId = -1;
@@ -1967,14 +1519,14 @@ btScalar btSequentialImpulseConstraintSolver::solveGroupCacheFriendlySetup(btCol
return 0.f;
}
-btScalar btSequentialImpulseConstraintSolver::solveSingleIterationInternal(btSISolverSingleIterationData& siData, int iteration, btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& infoGlobal)
+btScalar btSequentialImpulseConstraintSolver::solveSingleIteration(int iteration, btCollisionObject** /*bodies */, int /*numBodies*/, btPersistentManifold** /*manifoldPtr*/, int /*numManifolds*/, btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& infoGlobal, btIDebugDraw* /*debugDrawer*/)
{
BT_PROFILE("solveSingleIteration");
btScalar leastSquaresResidual = 0.f;
- int numNonContactPool = siData.m_tmpSolverNonContactConstraintPool.size();
- int numConstraintPool = siData.m_tmpSolverContactConstraintPool.size();
- int numFrictionPool = siData.m_tmpSolverContactFrictionConstraintPool.size();
+ int numNonContactPool = m_tmpSolverNonContactConstraintPool.size();
+ int numConstraintPool = m_tmpSolverContactConstraintPool.size();
+ int numFrictionPool = m_tmpSolverContactFrictionConstraintPool.size();
if (infoGlobal.m_solverMode & SOLVER_RANDMIZE_ORDER)
{
@@ -1982,10 +1534,10 @@ btScalar btSequentialImpulseConstraintSolver::solveSingleIterationInternal(btSIS
{
for (int j = 0; j < numNonContactPool; ++j)
{
- int tmp = siData.m_orderNonContactConstraintPool[j];
- int swapi = btRandInt2a(j + 1, siData.m_seed);
- siData.m_orderNonContactConstraintPool[j] = siData.m_orderNonContactConstraintPool[swapi];
- siData.m_orderNonContactConstraintPool[swapi] = tmp;
+ int tmp = m_orderNonContactConstraintPool[j];
+ int swapi = btRandInt2(j + 1);
+ m_orderNonContactConstraintPool[j] = m_orderNonContactConstraintPool[swapi];
+ m_orderNonContactConstraintPool[swapi] = tmp;
}
//contact/friction constraints are not solved more than
@@ -1993,30 +1545,30 @@ btScalar btSequentialImpulseConstraintSolver::solveSingleIterationInternal(btSIS
{
for (int j = 0; j < numConstraintPool; ++j)
{
- int tmp = siData.m_orderTmpConstraintPool[j];
- int swapi = btRandInt2a(j + 1, siData.m_seed);
- siData.m_orderTmpConstraintPool[j] = siData.m_orderTmpConstraintPool[swapi];
- siData.m_orderTmpConstraintPool[swapi] = tmp;
+ int tmp = m_orderTmpConstraintPool[j];
+ int swapi = btRandInt2(j + 1);
+ m_orderTmpConstraintPool[j] = m_orderTmpConstraintPool[swapi];
+ m_orderTmpConstraintPool[swapi] = tmp;
}
for (int j = 0; j < numFrictionPool; ++j)
{
- int tmp = siData.m_orderFrictionConstraintPool[j];
- int swapi = btRandInt2a(j + 1, siData.m_seed);
- siData.m_orderFrictionConstraintPool[j] = siData.m_orderFrictionConstraintPool[swapi];
- siData.m_orderFrictionConstraintPool[swapi] = tmp;
+ int tmp = m_orderFrictionConstraintPool[j];
+ int swapi = btRandInt2(j + 1);
+ m_orderFrictionConstraintPool[j] = m_orderFrictionConstraintPool[swapi];
+ m_orderFrictionConstraintPool[swapi] = tmp;
}
}
}
}
///solve all joint constraints
- for (int j = 0; j < siData.m_tmpSolverNonContactConstraintPool.size(); j++)
+ for (int j = 0; j < m_tmpSolverNonContactConstraintPool.size(); j++)
{
- btSolverConstraint& constraint = siData.m_tmpSolverNonContactConstraintPool[siData.m_orderNonContactConstraintPool[j]];
+ btSolverConstraint& constraint = m_tmpSolverNonContactConstraintPool[m_orderNonContactConstraintPool[j]];
if (iteration < constraint.m_overrideNumSolverIterations)
{
- btScalar residual = siData.m_resolveSingleConstraintRowGeneric(siData.m_tmpSolverBodyPool[constraint.m_solverBodyIdA], siData.m_tmpSolverBodyPool[constraint.m_solverBodyIdB], constraint);
+ btScalar residual = resolveSingleConstraintRowGeneric(m_tmpSolverBodyPool[constraint.m_solverBodyIdA], m_tmpSolverBodyPool[constraint.m_solverBodyIdB], constraint);
leastSquaresResidual = btMax(leastSquaresResidual, residual * residual);
}
}
@@ -2027,10 +1579,10 @@ btScalar btSequentialImpulseConstraintSolver::solveSingleIterationInternal(btSIS
{
if (constraints[j]->isEnabled())
{
- int bodyAid = siData.getSolverBody(constraints[j]->getRigidBodyA());
- int bodyBid = siData.getSolverBody(constraints[j]->getRigidBodyB());
- btSolverBody& bodyA = siData.m_tmpSolverBodyPool[bodyAid];
- btSolverBody& bodyB = siData.m_tmpSolverBodyPool[bodyBid];
+ int bodyAid = getOrInitSolverBody(constraints[j]->getRigidBodyA(), infoGlobal.m_timeStep);
+ int bodyBid = getOrInitSolverBody(constraints[j]->getRigidBodyB(), infoGlobal.m_timeStep);
+ btSolverBody& bodyA = m_tmpSolverBodyPool[bodyAid];
+ btSolverBody& bodyB = m_tmpSolverBodyPool[bodyBid];
constraints[j]->solveConstraintObsolete(bodyA, bodyB, infoGlobal.m_timeStep);
}
}
@@ -2038,7 +1590,7 @@ btScalar btSequentialImpulseConstraintSolver::solveSingleIterationInternal(btSIS
///solve all contact constraints
if (infoGlobal.m_solverMode & SOLVER_INTERLEAVE_CONTACT_AND_FRICTION_CONSTRAINTS)
{
- int numPoolConstraints = siData.m_tmpSolverContactConstraintPool.size();
+ int numPoolConstraints = m_tmpSolverContactConstraintPool.size();
int multiplier = (infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS) ? 2 : 1;
for (int c = 0; c < numPoolConstraints; c++)
@@ -2046,8 +1598,8 @@ btScalar btSequentialImpulseConstraintSolver::solveSingleIterationInternal(btSIS
btScalar totalImpulse = 0;
{
- const btSolverConstraint& solveManifold = siData.m_tmpSolverContactConstraintPool[siData.m_orderTmpConstraintPool[c]];
- btScalar residual = siData.m_resolveSingleConstraintRowLowerLimit(siData.m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA], siData.m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB], solveManifold);
+ const btSolverConstraint& solveManifold = m_tmpSolverContactConstraintPool[m_orderTmpConstraintPool[c]];
+ btScalar residual = resolveSingleConstraintRowLowerLimit(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA], m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB], solveManifold);
leastSquaresResidual = btMax(leastSquaresResidual, residual * residual);
totalImpulse = solveManifold.m_appliedImpulse;
@@ -2056,28 +1608,28 @@ btScalar btSequentialImpulseConstraintSolver::solveSingleIterationInternal(btSIS
if (applyFriction)
{
{
- btSolverConstraint& solveManifold = siData.m_tmpSolverContactFrictionConstraintPool[siData.m_orderFrictionConstraintPool[c * multiplier]];
+ btSolverConstraint& solveManifold = m_tmpSolverContactFrictionConstraintPool[m_orderFrictionConstraintPool[c * multiplier]];
if (totalImpulse > btScalar(0))
{
solveManifold.m_lowerLimit = -(solveManifold.m_friction * totalImpulse);
solveManifold.m_upperLimit = solveManifold.m_friction * totalImpulse;
- btScalar residual = siData.m_resolveSingleConstraintRowGeneric(siData.m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA], siData.m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB], solveManifold);
+ btScalar residual = resolveSingleConstraintRowGeneric(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA], m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB], solveManifold);
leastSquaresResidual = btMax(leastSquaresResidual, residual * residual);
}
}
if (infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS)
{
- btSolverConstraint& solveManifold = siData.m_tmpSolverContactFrictionConstraintPool[siData.m_orderFrictionConstraintPool[c * multiplier + 1]];
+ btSolverConstraint& solveManifold = m_tmpSolverContactFrictionConstraintPool[m_orderFrictionConstraintPool[c * multiplier + 1]];
if (totalImpulse > btScalar(0))
{
solveManifold.m_lowerLimit = -(solveManifold.m_friction * totalImpulse);
solveManifold.m_upperLimit = solveManifold.m_friction * totalImpulse;
- btScalar residual = siData.m_resolveSingleConstraintRowGeneric(siData.m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA], siData.m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB], solveManifold);
+ btScalar residual = resolveSingleConstraintRowGeneric(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA], m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB], solveManifold);
leastSquaresResidual = btMax(leastSquaresResidual, residual * residual);
}
}
@@ -2087,40 +1639,40 @@ btScalar btSequentialImpulseConstraintSolver::solveSingleIterationInternal(btSIS
else //SOLVER_INTERLEAVE_CONTACT_AND_FRICTION_CONSTRAINTS
{
//solve the friction constraints after all contact constraints, don't interleave them
- int numPoolConstraints = siData.m_tmpSolverContactConstraintPool.size();
+ int numPoolConstraints = m_tmpSolverContactConstraintPool.size();
int j;
for (j = 0; j < numPoolConstraints; j++)
{
- const btSolverConstraint& solveManifold = siData.m_tmpSolverContactConstraintPool[siData.m_orderTmpConstraintPool[j]];
- btScalar residual = siData.m_resolveSingleConstraintRowLowerLimit(siData.m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA], siData.m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB], solveManifold);
+ const btSolverConstraint& solveManifold = m_tmpSolverContactConstraintPool[m_orderTmpConstraintPool[j]];
+ btScalar residual = resolveSingleConstraintRowLowerLimit(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA], m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB], solveManifold);
leastSquaresResidual = btMax(leastSquaresResidual, residual * residual);
}
///solve all friction constraints
- int numFrictionPoolConstraints = siData.m_tmpSolverContactFrictionConstraintPool.size();
+ int numFrictionPoolConstraints = m_tmpSolverContactFrictionConstraintPool.size();
for (j = 0; j < numFrictionPoolConstraints; j++)
{
- btSolverConstraint& solveManifold = siData.m_tmpSolverContactFrictionConstraintPool[siData.m_orderFrictionConstraintPool[j]];
- btScalar totalImpulse = siData.m_tmpSolverContactConstraintPool[solveManifold.m_frictionIndex].m_appliedImpulse;
+ btSolverConstraint& solveManifold = m_tmpSolverContactFrictionConstraintPool[m_orderFrictionConstraintPool[j]];
+ btScalar totalImpulse = m_tmpSolverContactConstraintPool[solveManifold.m_frictionIndex].m_appliedImpulse;
if (totalImpulse > btScalar(0))
{
solveManifold.m_lowerLimit = -(solveManifold.m_friction * totalImpulse);
solveManifold.m_upperLimit = solveManifold.m_friction * totalImpulse;
- btScalar residual = siData.m_resolveSingleConstraintRowGeneric(siData.m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA], siData.m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB], solveManifold);
+ btScalar residual = resolveSingleConstraintRowGeneric(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA], m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB], solveManifold);
leastSquaresResidual = btMax(leastSquaresResidual, residual * residual);
}
}
}
- int numRollingFrictionPoolConstraints = siData.m_tmpSolverContactRollingFrictionConstraintPool.size();
+ int numRollingFrictionPoolConstraints = m_tmpSolverContactRollingFrictionConstraintPool.size();
for (int j = 0; j < numRollingFrictionPoolConstraints; j++)
{
- btSolverConstraint& rollingFrictionConstraint = siData.m_tmpSolverContactRollingFrictionConstraintPool[j];
- btScalar totalImpulse = siData.m_tmpSolverContactConstraintPool[rollingFrictionConstraint.m_frictionIndex].m_appliedImpulse;
+ btSolverConstraint& rollingFrictionConstraint = m_tmpSolverContactRollingFrictionConstraintPool[j];
+ btScalar totalImpulse = m_tmpSolverContactConstraintPool[rollingFrictionConstraint.m_frictionIndex].m_appliedImpulse;
if (totalImpulse > btScalar(0))
{
btScalar rollingFrictionMagnitude = rollingFrictionConstraint.m_friction * totalImpulse;
@@ -2130,7 +1682,7 @@ btScalar btSequentialImpulseConstraintSolver::solveSingleIterationInternal(btSIS
rollingFrictionConstraint.m_lowerLimit = -rollingFrictionMagnitude;
rollingFrictionConstraint.m_upperLimit = rollingFrictionMagnitude;
- btScalar residual = siData.m_resolveSingleConstraintRowGeneric(siData.m_tmpSolverBodyPool[rollingFrictionConstraint.m_solverBodyIdA], siData.m_tmpSolverBodyPool[rollingFrictionConstraint.m_solverBodyIdB], rollingFrictionConstraint);
+ btScalar residual = resolveSingleConstraintRowGeneric(m_tmpSolverBodyPool[rollingFrictionConstraint.m_solverBodyIdA], m_tmpSolverBodyPool[rollingFrictionConstraint.m_solverBodyIdB], rollingFrictionConstraint);
leastSquaresResidual = btMax(leastSquaresResidual, residual * residual);
}
}
@@ -2138,56 +1690,8 @@ btScalar btSequentialImpulseConstraintSolver::solveSingleIterationInternal(btSIS
return leastSquaresResidual;
}
-
-btScalar btSequentialImpulseConstraintSolver::solveSingleIteration(int iteration, btCollisionObject** /*bodies */, int /*numBodies*/, btPersistentManifold** /*manifoldPtr*/, int /*numManifolds*/, btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& infoGlobal, btIDebugDraw* /*debugDrawer*/)
-{
- btSISolverSingleIterationData siData(m_tmpSolverBodyPool,
- m_tmpSolverContactConstraintPool,
- m_tmpSolverNonContactConstraintPool,
- m_tmpSolverContactFrictionConstraintPool,
- m_tmpSolverContactRollingFrictionConstraintPool,
- m_orderTmpConstraintPool,
- m_orderNonContactConstraintPool,
- m_orderFrictionConstraintPool,
- m_tmpConstraintSizesPool,
- m_resolveSingleConstraintRowGeneric,
- m_resolveSingleConstraintRowLowerLimit,
- m_resolveSplitPenetrationImpulse,
- m_kinematicBodyUniqueIdToSolverBodyTable,
- m_btSeed2,
- m_fixedBodyId,
- m_maxOverrideNumSolverIterations);
-
- btScalar leastSquaresResidual = btSequentialImpulseConstraintSolver::solveSingleIterationInternal(siData,
- iteration, constraints, numConstraints, infoGlobal);
- return leastSquaresResidual;
-}
-
void btSequentialImpulseConstraintSolver::solveGroupCacheFriendlySplitImpulseIterations(btCollisionObject** bodies, int numBodies, btPersistentManifold** manifoldPtr, int numManifolds, btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& infoGlobal, btIDebugDraw* debugDrawer)
{
- btSISolverSingleIterationData siData(m_tmpSolverBodyPool,
- m_tmpSolverContactConstraintPool,
- m_tmpSolverNonContactConstraintPool,
- m_tmpSolverContactFrictionConstraintPool,
- m_tmpSolverContactRollingFrictionConstraintPool,
- m_orderTmpConstraintPool,
- m_orderNonContactConstraintPool,
- m_orderFrictionConstraintPool,
- m_tmpConstraintSizesPool,
- m_resolveSingleConstraintRowGeneric,
- m_resolveSingleConstraintRowLowerLimit,
- m_resolveSplitPenetrationImpulse,
- m_kinematicBodyUniqueIdToSolverBodyTable,
- m_btSeed2,
- m_fixedBodyId,
- m_maxOverrideNumSolverIterations);
-
- solveGroupCacheFriendlySplitImpulseIterationsInternal(siData,
- bodies, numBodies, manifoldPtr, numManifolds, constraints, numConstraints, infoGlobal, debugDrawer);
-
-}
-void btSequentialImpulseConstraintSolver::solveGroupCacheFriendlySplitImpulseIterationsInternal(btSISolverSingleIterationData& siData, btCollisionObject** bodies, int numBodies, btPersistentManifold** manifoldPtr, int numManifolds, btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& infoGlobal, btIDebugDraw* debugDrawer)
-{
BT_PROFILE("solveGroupCacheFriendlySplitImpulseIterations");
int iteration;
if (infoGlobal.m_splitImpulse)
@@ -2197,13 +1701,13 @@ void btSequentialImpulseConstraintSolver::solveGroupCacheFriendlySplitImpulseIte
{
btScalar leastSquaresResidual = 0.f;
{
- int numPoolConstraints = siData.m_tmpSolverContactConstraintPool.size();
+ int numPoolConstraints = m_tmpSolverContactConstraintPool.size();
int j;
for (j = 0; j < numPoolConstraints; j++)
{
- const btSolverConstraint& solveManifold = siData.m_tmpSolverContactConstraintPool[siData.m_orderTmpConstraintPool[j]];
+ const btSolverConstraint& solveManifold = m_tmpSolverContactConstraintPool[m_orderTmpConstraintPool[j]];
- btScalar residual = siData.m_resolveSplitPenetrationImpulse(siData.m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA], siData.m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB], solveManifold);
+ btScalar residual = resolveSplitPenetrationImpulse(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA], m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB], solveManifold);
leastSquaresResidual = btMax(leastSquaresResidual, residual * residual);
}
}
@@ -2254,42 +1758,31 @@ btScalar btSequentialImpulseConstraintSolver::solveGroupCacheFriendlyIterations(
return 0.f;
}
-void btSequentialImpulseConstraintSolver::writeBackContactsInternal(btConstraintArray& tmpSolverContactConstraintPool, btConstraintArray& tmpSolverContactFrictionConstraintPool, int iBegin, int iEnd, const btContactSolverInfo& infoGlobal)
+void btSequentialImpulseConstraintSolver::writeBackContacts(int iBegin, int iEnd, const btContactSolverInfo& infoGlobal)
{
for (int j = iBegin; j < iEnd; j++)
{
- const btSolverConstraint& solveManifold = tmpSolverContactConstraintPool[j];
+ const btSolverConstraint& solveManifold = m_tmpSolverContactConstraintPool[j];
btManifoldPoint* pt = (btManifoldPoint*)solveManifold.m_originalContactPoint;
btAssert(pt);
pt->m_appliedImpulse = solveManifold.m_appliedImpulse;
// float f = m_tmpSolverContactFrictionConstraintPool[solveManifold.m_frictionIndex].m_appliedImpulse;
// printf("pt->m_appliedImpulseLateral1 = %f\n", f);
- pt->m_appliedImpulseLateral1 = tmpSolverContactFrictionConstraintPool[solveManifold.m_frictionIndex].m_appliedImpulse;
+ pt->m_appliedImpulseLateral1 = m_tmpSolverContactFrictionConstraintPool[solveManifold.m_frictionIndex].m_appliedImpulse;
//printf("pt->m_appliedImpulseLateral1 = %f\n", pt->m_appliedImpulseLateral1);
if ((infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS))
{
- pt->m_appliedImpulseLateral2 = tmpSolverContactFrictionConstraintPool[solveManifold.m_frictionIndex + 1].m_appliedImpulse;
+ pt->m_appliedImpulseLateral2 = m_tmpSolverContactFrictionConstraintPool[solveManifold.m_frictionIndex + 1].m_appliedImpulse;
}
//do a callback here?
}
}
-void btSequentialImpulseConstraintSolver::writeBackContacts(int iBegin, int iEnd, const btContactSolverInfo& infoGlobal)
-{
- writeBackContactsInternal(m_tmpSolverContactConstraintPool, m_tmpSolverContactFrictionConstraintPool, iBegin, iEnd, infoGlobal);
-
-}
-
void btSequentialImpulseConstraintSolver::writeBackJoints(int iBegin, int iEnd, const btContactSolverInfo& infoGlobal)
{
- writeBackJointsInternal(m_tmpSolverNonContactConstraintPool, iBegin, iEnd, infoGlobal);
-}
-
-void btSequentialImpulseConstraintSolver::writeBackJointsInternal(btConstraintArray& tmpSolverNonContactConstraintPool, int iBegin, int iEnd, const btContactSolverInfo& infoGlobal)
-{
for (int j = iBegin; j < iEnd; j++)
{
- const btSolverConstraint& solverConstr = tmpSolverNonContactConstraintPool[j];
+ const btSolverConstraint& solverConstr = m_tmpSolverNonContactConstraintPool[j];
btTypedConstraint* constr = (btTypedConstraint*)solverConstr.m_originalContactPoint;
btJointFeedback* fb = constr->getJointFeedback();
if (fb)
@@ -2310,79 +1803,53 @@ void btSequentialImpulseConstraintSolver::writeBackJointsInternal(btConstraintAr
void btSequentialImpulseConstraintSolver::writeBackBodies(int iBegin, int iEnd, const btContactSolverInfo& infoGlobal)
{
- writeBackBodiesInternal(m_tmpSolverBodyPool, iBegin, iEnd, infoGlobal);
-}
-void btSequentialImpulseConstraintSolver::writeBackBodiesInternal(btAlignedObjectArray<btSolverBody>& tmpSolverBodyPool, int iBegin, int iEnd, const btContactSolverInfo& infoGlobal)
-{
for (int i = iBegin; i < iEnd; i++)
{
- btRigidBody* body = tmpSolverBodyPool[i].m_originalBody;
+ btRigidBody* body = m_tmpSolverBodyPool[i].m_originalBody;
if (body)
{
if (infoGlobal.m_splitImpulse)
- tmpSolverBodyPool[i].writebackVelocityAndTransform(infoGlobal.m_timeStep, infoGlobal.m_splitImpulseTurnErp);
+ m_tmpSolverBodyPool[i].writebackVelocityAndTransform(infoGlobal.m_timeStep, infoGlobal.m_splitImpulseTurnErp);
else
- tmpSolverBodyPool[i].writebackVelocity();
+ m_tmpSolverBodyPool[i].writebackVelocity();
- tmpSolverBodyPool[i].m_originalBody->setLinearVelocity(
- tmpSolverBodyPool[i].m_linearVelocity +
- tmpSolverBodyPool[i].m_externalForceImpulse);
+ m_tmpSolverBodyPool[i].m_originalBody->setLinearVelocity(
+ m_tmpSolverBodyPool[i].m_linearVelocity +
+ m_tmpSolverBodyPool[i].m_externalForceImpulse);
- tmpSolverBodyPool[i].m_originalBody->setAngularVelocity(
- tmpSolverBodyPool[i].m_angularVelocity +
- tmpSolverBodyPool[i].m_externalTorqueImpulse);
+ m_tmpSolverBodyPool[i].m_originalBody->setAngularVelocity(
+ m_tmpSolverBodyPool[i].m_angularVelocity +
+ m_tmpSolverBodyPool[i].m_externalTorqueImpulse);
if (infoGlobal.m_splitImpulse)
- tmpSolverBodyPool[i].m_originalBody->setWorldTransform(tmpSolverBodyPool[i].m_worldTransform);
+ m_tmpSolverBodyPool[i].m_originalBody->setWorldTransform(m_tmpSolverBodyPool[i].m_worldTransform);
- tmpSolverBodyPool[i].m_originalBody->setCompanionId(-1);
+ m_tmpSolverBodyPool[i].m_originalBody->setCompanionId(-1);
}
}
}
-btScalar btSequentialImpulseConstraintSolver::solveGroupCacheFriendlyFinishInternal(btSISolverSingleIterationData& siData, btCollisionObject** bodies, int numBodies, const btContactSolverInfo& infoGlobal)
+btScalar btSequentialImpulseConstraintSolver::solveGroupCacheFriendlyFinish(btCollisionObject** bodies, int numBodies, const btContactSolverInfo& infoGlobal)
{
BT_PROFILE("solveGroupCacheFriendlyFinish");
if (infoGlobal.m_solverMode & SOLVER_USE_WARMSTARTING)
{
- writeBackContactsInternal(siData.m_tmpSolverContactConstraintPool, siData.m_tmpSolverContactFrictionConstraintPool, 0, siData.m_tmpSolverContactConstraintPool.size(), infoGlobal);
+ writeBackContacts(0, m_tmpSolverContactConstraintPool.size(), infoGlobal);
}
- writeBackJointsInternal(siData.m_tmpSolverNonContactConstraintPool, 0, siData.m_tmpSolverNonContactConstraintPool.size(), infoGlobal);
- writeBackBodiesInternal(siData.m_tmpSolverBodyPool, 0, siData.m_tmpSolverBodyPool.size(), infoGlobal);
+ writeBackJoints(0, m_tmpSolverNonContactConstraintPool.size(), infoGlobal);
+ writeBackBodies(0, m_tmpSolverBodyPool.size(), infoGlobal);
- siData.m_tmpSolverContactConstraintPool.resizeNoInitialize(0);
- siData.m_tmpSolverNonContactConstraintPool.resizeNoInitialize(0);
- siData.m_tmpSolverContactFrictionConstraintPool.resizeNoInitialize(0);
- siData.m_tmpSolverContactRollingFrictionConstraintPool.resizeNoInitialize(0);
+ m_tmpSolverContactConstraintPool.resizeNoInitialize(0);
+ m_tmpSolverNonContactConstraintPool.resizeNoInitialize(0);
+ m_tmpSolverContactFrictionConstraintPool.resizeNoInitialize(0);
+ m_tmpSolverContactRollingFrictionConstraintPool.resizeNoInitialize(0);
- siData.m_tmpSolverBodyPool.resizeNoInitialize(0);
+ m_tmpSolverBodyPool.resizeNoInitialize(0);
return 0.f;
}
-btScalar btSequentialImpulseConstraintSolver::solveGroupCacheFriendlyFinish(btCollisionObject** bodies, int numBodies, const btContactSolverInfo& infoGlobal)
-{
- btSISolverSingleIterationData siData(m_tmpSolverBodyPool,
- m_tmpSolverContactConstraintPool,
- m_tmpSolverNonContactConstraintPool,
- m_tmpSolverContactFrictionConstraintPool,
- m_tmpSolverContactRollingFrictionConstraintPool,
- m_orderTmpConstraintPool,
- m_orderNonContactConstraintPool,
- m_orderFrictionConstraintPool,
- m_tmpConstraintSizesPool,
- m_resolveSingleConstraintRowGeneric,
- m_resolveSingleConstraintRowLowerLimit,
- m_resolveSplitPenetrationImpulse,
- m_kinematicBodyUniqueIdToSolverBodyTable,
- m_btSeed2,
- m_fixedBodyId,
- m_maxOverrideNumSolverIterations);
-
- return btSequentialImpulseConstraintSolver::solveGroupCacheFriendlyFinishInternal(siData, bodies, numBodies, infoGlobal);
-}
-
/// btSequentialImpulseConstraintSolver Sequentially applies impulses
btScalar btSequentialImpulseConstraintSolver::solveGroup(btCollisionObject** bodies, int numBodies, btPersistentManifold** manifoldPtr, int numManifolds, btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& infoGlobal, btIDebugDraw* debugDrawer, btDispatcher* /*dispatcher*/)
{
@@ -2401,4 +1868,4 @@ btScalar btSequentialImpulseConstraintSolver::solveGroup(btCollisionObject** bod
void btSequentialImpulseConstraintSolver::reset()
{
m_btSeed2 = 0;
-} \ No newline at end of file
+}
diff --git a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.h b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.h
index 2b88e25be7..f3ef02fccc 100644
--- a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.h
+++ b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.h
@@ -29,68 +29,6 @@ class btCollisionObject;
typedef btScalar (*btSingleConstraintRowSolver)(btSolverBody&, btSolverBody&, const btSolverConstraint&);
-struct btSISolverSingleIterationData
-{
- btAlignedObjectArray<btSolverBody>& m_tmpSolverBodyPool;
- btConstraintArray& m_tmpSolverContactConstraintPool;
- btConstraintArray& m_tmpSolverNonContactConstraintPool;
- btConstraintArray& m_tmpSolverContactFrictionConstraintPool;
- btConstraintArray& m_tmpSolverContactRollingFrictionConstraintPool;
-
- btAlignedObjectArray<int>& m_orderTmpConstraintPool;
- btAlignedObjectArray<int>& m_orderNonContactConstraintPool;
- btAlignedObjectArray<int>& m_orderFrictionConstraintPool;
- btAlignedObjectArray<btTypedConstraint::btConstraintInfo1>& m_tmpConstraintSizesPool;
- unsigned long& m_seed;
-
- btSingleConstraintRowSolver& m_resolveSingleConstraintRowGeneric;
- btSingleConstraintRowSolver& m_resolveSingleConstraintRowLowerLimit;
- btSingleConstraintRowSolver& m_resolveSplitPenetrationImpulse;
- btAlignedObjectArray<int>& m_kinematicBodyUniqueIdToSolverBodyTable;
- int& m_fixedBodyId;
- int& m_maxOverrideNumSolverIterations;
- int getOrInitSolverBody(btCollisionObject & body, btScalar timeStep);
- static void initSolverBody(btSolverBody * solverBody, btCollisionObject * collisionObject, btScalar timeStep);
- int getSolverBody(btCollisionObject& body) const;
-
-
- btSISolverSingleIterationData(btAlignedObjectArray<btSolverBody>& tmpSolverBodyPool,
- btConstraintArray& tmpSolverContactConstraintPool,
- btConstraintArray& tmpSolverNonContactConstraintPool,
- btConstraintArray& tmpSolverContactFrictionConstraintPool,
- btConstraintArray& tmpSolverContactRollingFrictionConstraintPool,
- btAlignedObjectArray<int>& orderTmpConstraintPool,
- btAlignedObjectArray<int>& orderNonContactConstraintPool,
- btAlignedObjectArray<int>& orderFrictionConstraintPool,
- btAlignedObjectArray<btTypedConstraint::btConstraintInfo1>& tmpConstraintSizesPool,
- btSingleConstraintRowSolver& resolveSingleConstraintRowGeneric,
- btSingleConstraintRowSolver& resolveSingleConstraintRowLowerLimit,
- btSingleConstraintRowSolver& resolveSplitPenetrationImpulse,
- btAlignedObjectArray<int>& kinematicBodyUniqueIdToSolverBodyTable,
- unsigned long& seed,
- int& fixedBodyId,
- int& maxOverrideNumSolverIterations
- )
- :m_tmpSolverBodyPool(tmpSolverBodyPool),
- m_tmpSolverContactConstraintPool(tmpSolverContactConstraintPool),
- m_tmpSolverNonContactConstraintPool(tmpSolverNonContactConstraintPool),
- m_tmpSolverContactFrictionConstraintPool(tmpSolverContactFrictionConstraintPool),
- m_tmpSolverContactRollingFrictionConstraintPool(tmpSolverContactRollingFrictionConstraintPool),
- m_orderTmpConstraintPool(orderTmpConstraintPool),
- m_orderNonContactConstraintPool(orderNonContactConstraintPool),
- m_orderFrictionConstraintPool(orderFrictionConstraintPool),
- m_tmpConstraintSizesPool(tmpConstraintSizesPool),
- m_seed(seed),
- m_resolveSingleConstraintRowGeneric(resolveSingleConstraintRowGeneric),
- m_resolveSingleConstraintRowLowerLimit(resolveSingleConstraintRowLowerLimit),
- m_resolveSplitPenetrationImpulse(resolveSplitPenetrationImpulse),
- m_kinematicBodyUniqueIdToSolverBodyTable(kinematicBodyUniqueIdToSolverBodyTable),
- m_fixedBodyId(fixedBodyId),
- m_maxOverrideNumSolverIterations(maxOverrideNumSolverIterations)
- {
- }
-};
-
struct btSolverAnalyticsData
{
btSolverAnalyticsData()
@@ -178,7 +116,6 @@ protected:
virtual void convertJoints(btTypedConstraint * *constraints, int numConstraints, const btContactSolverInfo& infoGlobal);
void convertJoint(btSolverConstraint * currentConstraintRow, btTypedConstraint * constraint, const btTypedConstraint::btConstraintInfo1& info1, int solverBodyIdA, int solverBodyIdB, const btContactSolverInfo& infoGlobal);
-
virtual void convertBodies(btCollisionObject * *bodies, int numBodies, const btContactSolverInfo& infoGlobal);
btScalar resolveSplitPenetrationSIMD(btSolverBody & bodyA, btSolverBody & bodyB, const btSolverConstraint& contactConstraint)
@@ -204,8 +141,7 @@ protected:
return m_resolveSplitPenetrationImpulse(bodyA, bodyB, contactConstraint);
}
-public:
-
+protected:
void writeBackContacts(int iBegin, int iEnd, const btContactSolverInfo& infoGlobal);
void writeBackJoints(int iBegin, int iEnd, const btContactSolverInfo& infoGlobal);
void writeBackBodies(int iBegin, int iEnd, const btContactSolverInfo& infoGlobal);
@@ -213,7 +149,6 @@ public:
virtual btScalar solveGroupCacheFriendlyFinish(btCollisionObject * *bodies, int numBodies, const btContactSolverInfo& infoGlobal);
virtual btScalar solveSingleIteration(int iteration, btCollisionObject** bodies, int numBodies, btPersistentManifold** manifoldPtr, int numManifolds, btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& infoGlobal, btIDebugDraw* debugDrawer);
-
virtual btScalar solveGroupCacheFriendlySetup(btCollisionObject * *bodies, int numBodies, btPersistentManifold** manifoldPtr, int numManifolds, btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& infoGlobal, btIDebugDraw* debugDrawer);
virtual btScalar solveGroupCacheFriendlyIterations(btCollisionObject * *bodies, int numBodies, btPersistentManifold** manifoldPtr, int numManifolds, btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& infoGlobal, btIDebugDraw* debugDrawer);
@@ -225,51 +160,12 @@ public:
virtual btScalar solveGroup(btCollisionObject * *bodies, int numBodies, btPersistentManifold** manifold, int numManifolds, btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& info, btIDebugDraw* debugDrawer, btDispatcher* dispatcher);
- static btScalar solveSingleIterationInternal(btSISolverSingleIterationData& siData, int iteration, btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& infoGlobal);
- static void convertBodiesInternal(btSISolverSingleIterationData& siData, btCollisionObject** bodies, int numBodies, const btContactSolverInfo& infoGlobal);
- static void convertJointsInternal(btSISolverSingleIterationData& siData, btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& infoGlobal);
- static void convertContactInternal(btSISolverSingleIterationData& siData, btPersistentManifold * manifold, const btContactSolverInfo& infoGlobal);
- static void setupContactConstraintInternal(btSISolverSingleIterationData& siData, btSolverConstraint& solverConstraint, int solverBodyIdA, int solverBodyIdB, btManifoldPoint& cp, const btContactSolverInfo& infoGlobal, btScalar& relaxation,
- const btVector3& rel_pos1, const btVector3& rel_pos2);
- static btScalar restitutionCurveInternal(btScalar rel_vel, btScalar restitution, btScalar velocityThreshold);
- static btSolverConstraint& addTorsionalFrictionConstraintInternal(btAlignedObjectArray<btSolverBody>& tmpSolverBodyPool, btConstraintArray& tmpSolverContactRollingFrictionConstraintPool, const btVector3& normalAxis, int solverBodyIdA, int solverBodyIdB, int frictionIndex, btManifoldPoint& cp, btScalar combinedTorsionalFriction, const btVector3& rel_pos1, const btVector3& rel_pos2, btCollisionObject* colObj0, btCollisionObject* colObj1, btScalar relaxation, btScalar desiredVelocity = 0, btScalar cfmSlip = 0.);
- static void setupTorsionalFrictionConstraintInternal(btAlignedObjectArray<btSolverBody>& tmpSolverBodyPool, btSolverConstraint& solverConstraint, const btVector3& normalAxis1, int solverBodyIdA, int solverBodyIdB,
- btManifoldPoint& cp, btScalar combinedTorsionalFriction, const btVector3& rel_pos1, const btVector3& rel_pos2,
- btCollisionObject* colObj0, btCollisionObject* colObj1, btScalar relaxation,
- btScalar desiredVelocity, btScalar cfmSlip);
- static void setupFrictionConstraintInternal(btAlignedObjectArray<btSolverBody>& tmpSolverBodyPool, btSolverConstraint& solverConstraint, const btVector3& normalAxis, int solverBodyIdA, int solverBodyIdB, btManifoldPoint& cp, const btVector3& rel_pos1, const btVector3& rel_pos2, btCollisionObject* colObj0, btCollisionObject* colObj1, btScalar relaxation, const btContactSolverInfo& infoGlobal, btScalar desiredVelocity, btScalar cfmSlip);
- static btSolverConstraint& addFrictionConstraintInternal(btAlignedObjectArray<btSolverBody>& tmpSolverBodyPool, btConstraintArray& tmpSolverContactFrictionConstraintPool, const btVector3& normalAxis, int solverBodyIdA, int solverBodyIdB, int frictionIndex, btManifoldPoint& cp, const btVector3& rel_pos1, const btVector3& rel_pos2, btCollisionObject* colObj0, btCollisionObject* colObj1, btScalar relaxation, const btContactSolverInfo& infoGlobal, btScalar desiredVelocity = 0., btScalar cfmSlip = 0.);
- static void setFrictionConstraintImpulseInternal(btAlignedObjectArray<btSolverBody>& tmpSolverBodyPool, btConstraintArray& tmpSolverContactFrictionConstraintPool,
-
- btSolverConstraint& solverConstraint,
- int solverBodyIdA, int solverBodyIdB,
- btManifoldPoint& cp, const btContactSolverInfo& infoGlobal);
- static void convertJointInternal(btAlignedObjectArray<btSolverBody>& tmpSolverBodyPool,
- int& maxOverrideNumSolverIterations,
- btSolverConstraint* currentConstraintRow,
- btTypedConstraint* constraint,
- const btTypedConstraint::btConstraintInfo1& info1,
- int solverBodyIdA,
- int solverBodyIdB,
- const btContactSolverInfo& infoGlobal);
-
- static btScalar solveGroupCacheFriendlyFinishInternal(btSISolverSingleIterationData& siData, btCollisionObject** bodies, int numBodies, const btContactSolverInfo& infoGlobal);
-
- static void writeBackContactsInternal(btConstraintArray& tmpSolverContactConstraintPool, btConstraintArray& tmpSolverContactFrictionConstraintPool, int iBegin, int iEnd, const btContactSolverInfo& infoGlobal);
-
- static void writeBackJointsInternal(btConstraintArray& tmpSolverNonContactConstraintPool, int iBegin, int iEnd, const btContactSolverInfo& infoGlobal);
- static void writeBackBodiesInternal(btAlignedObjectArray<btSolverBody>& tmpSolverBodyPool, int iBegin, int iEnd, const btContactSolverInfo& infoGlobal);
- static void solveGroupCacheFriendlySplitImpulseIterationsInternal(btSISolverSingleIterationData& siData, btCollisionObject** bodies, int numBodies, btPersistentManifold** manifoldPtr, int numManifolds, btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& infoGlobal, btIDebugDraw* debugDrawer);
-
-
///clear internal cached data and reset random seed
virtual void reset();
unsigned long btRand2();
- int btRandInt2(int n);
- static unsigned long btRand2a(unsigned long& seed);
- static int btRandInt2a(int n, unsigned long& seed);
+ int btRandInt2(int n);
void setRandSeed(unsigned long seed)
{
@@ -305,18 +201,14 @@ public:
///Various implementations of solving a single constraint row using a generic equality constraint, using scalar reference, SSE2 or SSE4
- static btSingleConstraintRowSolver getScalarConstraintRowSolverGeneric();
- static btSingleConstraintRowSolver getSSE2ConstraintRowSolverGeneric();
- static btSingleConstraintRowSolver getSSE4_1ConstraintRowSolverGeneric();
+ btSingleConstraintRowSolver getScalarConstraintRowSolverGeneric();
+ btSingleConstraintRowSolver getSSE2ConstraintRowSolverGeneric();
+ btSingleConstraintRowSolver getSSE4_1ConstraintRowSolverGeneric();
///Various implementations of solving a single constraint row using an inequality (lower limit) constraint, using scalar reference, SSE2 or SSE4
- static btSingleConstraintRowSolver getScalarConstraintRowSolverLowerLimit();
- static btSingleConstraintRowSolver getSSE2ConstraintRowSolverLowerLimit();
- static btSingleConstraintRowSolver getSSE4_1ConstraintRowSolverLowerLimit();
-
- static btSingleConstraintRowSolver getScalarSplitPenetrationImpulseGeneric();
- static btSingleConstraintRowSolver getSSE2SplitPenetrationImpulseGeneric();
-
+ btSingleConstraintRowSolver getScalarConstraintRowSolverLowerLimit();
+ btSingleConstraintRowSolver getSSE2ConstraintRowSolverLowerLimit();
+ btSingleConstraintRowSolver getSSE4_1ConstraintRowSolverLowerLimit();
btSolverAnalyticsData m_analyticsData;
};
diff --git a/thirdparty/bullet/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.cpp b/thirdparty/bullet/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.cpp
index dfbbdb154f..a3c9f42eb9 100644
--- a/thirdparty/bullet/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.cpp
+++ b/thirdparty/bullet/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.cpp
@@ -1436,9 +1436,7 @@ void btDiscreteDynamicsWorld::serializeDynamicsWorldInfo(btSerializer* serialize
worldInfo->m_solverInfo.m_splitImpulse = getSolverInfo().m_splitImpulse;
- // Fill padding with zeros to appease msan.
- memset(worldInfo->m_solverInfo.m_padding, 0, sizeof(worldInfo->m_solverInfo.m_padding));
-
+
#ifdef BT_USE_DOUBLE_PRECISION
const char* structType = "btDynamicsWorldDoubleData";
#else //BT_USE_DOUBLE_PRECISION
diff --git a/thirdparty/bullet/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h b/thirdparty/bullet/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h
index 7fe9619213..73607c61fd 100644
--- a/thirdparty/bullet/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h
+++ b/thirdparty/bullet/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h
@@ -17,7 +17,6 @@ subject to the following restrictions:
#define BT_DISCRETE_DYNAMICS_WORLD_H
#include "btDynamicsWorld.h"
-
class btDispatcher;
class btOverlappingPairCache;
class btConstraintSolver;
@@ -26,6 +25,7 @@ class btTypedConstraint;
class btActionInterface;
class btPersistentManifold;
class btIDebugDraw;
+
struct InplaceSolverIslandCallback;
#include "LinearMath/btAlignedObjectArray.h"
@@ -76,7 +76,7 @@ protected:
virtual void calculateSimulationIslands();
- virtual void solveConstraints(btContactSolverInfo & solverInfo);
+
virtual void updateActivationState(btScalar timeStep);
@@ -95,7 +95,7 @@ protected:
void serializeRigidBodies(btSerializer * serializer);
void serializeDynamicsWorldInfo(btSerializer * serializer);
-
+
public:
BT_DECLARE_ALIGNED_ALLOCATOR();
@@ -107,6 +107,8 @@ public:
///if maxSubSteps > 0, it will interpolate motion between fixedTimeStep's
virtual int stepSimulation(btScalar timeStep, int maxSubSteps = 1, btScalar fixedTimeStep = btScalar(1.) / btScalar(60.));
+ virtual void solveConstraints(btContactSolverInfo & solverInfo);
+
virtual void synchronizeMotionStates();
///this can be useful to synchronize a single rigid body -> graphics object
@@ -227,6 +229,16 @@ public:
{
return m_latencyMotionStateInterpolation;
}
+
+ btAlignedObjectArray<btRigidBody*>& getNonStaticRigidBodies()
+ {
+ return m_nonStaticRigidBodies;
+ }
+
+ const btAlignedObjectArray<btRigidBody*>& getNonStaticRigidBodies() const
+ {
+ return m_nonStaticRigidBodies;
+ }
};
#endif //BT_DISCRETE_DYNAMICS_WORLD_H
diff --git a/thirdparty/bullet/BulletDynamics/Dynamics/btDynamicsWorld.h b/thirdparty/bullet/BulletDynamics/Dynamics/btDynamicsWorld.h
index eadd8c12e7..3c55234a8a 100644
--- a/thirdparty/bullet/BulletDynamics/Dynamics/btDynamicsWorld.h
+++ b/thirdparty/bullet/BulletDynamics/Dynamics/btDynamicsWorld.h
@@ -34,7 +34,8 @@ enum btDynamicsWorldType
BT_CONTINUOUS_DYNAMICS_WORLD = 3,
BT_SOFT_RIGID_DYNAMICS_WORLD = 4,
BT_GPU_DYNAMICS_WORLD = 5,
- BT_SOFT_MULTIBODY_DYNAMICS_WORLD = 6
+ BT_SOFT_MULTIBODY_DYNAMICS_WORLD = 6,
+ BT_DEFORMABLE_MULTIBODY_DYNAMICS_WORLD = 7
};
///The btDynamicsWorld is the interface class for several dynamics implementation, basic, discrete, parallel, and continuous etc.
diff --git a/thirdparty/bullet/BulletDynamics/Dynamics/btRigidBody.cpp b/thirdparty/bullet/BulletDynamics/Dynamics/btRigidBody.cpp
index f4bcabada2..9e8705b001 100644
--- a/thirdparty/bullet/BulletDynamics/Dynamics/btRigidBody.cpp
+++ b/thirdparty/bullet/BulletDynamics/Dynamics/btRigidBody.cpp
@@ -206,6 +206,14 @@ void btRigidBody::applyGravity()
applyCentralForce(m_gravity);
}
+void btRigidBody::clearGravity()
+{
+ if (isStaticOrKinematicObject())
+ return;
+
+ applyCentralForce(-m_gravity);
+}
+
void btRigidBody::proceedToTransform(const btTransform& newTrans)
{
setCenterOfMassTransform(newTrans);
diff --git a/thirdparty/bullet/BulletDynamics/Dynamics/btRigidBody.h b/thirdparty/bullet/BulletDynamics/Dynamics/btRigidBody.h
index 05f270a4b8..39d47cbbda 100644
--- a/thirdparty/bullet/BulletDynamics/Dynamics/btRigidBody.h
+++ b/thirdparty/bullet/BulletDynamics/Dynamics/btRigidBody.h
@@ -205,6 +205,8 @@ public:
void saveKinematicState(btScalar step);
void applyGravity();
+
+ void clearGravity();
void setGravity(const btVector3& acceleration);
@@ -259,6 +261,7 @@ public:
m_invMass = m_linearFactor * m_inverseMass;
}
btScalar getInvMass() const { return m_inverseMass; }
+ btScalar getMass() const { return m_inverseMass == btScalar(0.) ? btScalar(0.) : btScalar(1.0) / m_inverseMass; }
const btMatrix3x3& getInvInertiaTensorWorld() const
{
return m_invInertiaTensorWorld;
@@ -331,6 +334,48 @@ public:
}
}
}
+
+ void applyPushImpulse(const btVector3& impulse, const btVector3& rel_pos)
+ {
+ if (m_inverseMass != btScalar(0.))
+ {
+ applyCentralPushImpulse(impulse);
+ if (m_angularFactor)
+ {
+ applyTorqueTurnImpulse(rel_pos.cross(impulse * m_linearFactor));
+ }
+ }
+ }
+
+ btVector3 getPushVelocity()
+ {
+ return m_pushVelocity;
+ }
+
+ btVector3 getTurnVelocity()
+ {
+ return m_turnVelocity;
+ }
+
+ void setPushVelocity(const btVector3& v)
+ {
+ m_pushVelocity = v;
+ }
+
+ void setTurnVelocity(const btVector3& v)
+ {
+ m_turnVelocity = v;
+ }
+
+ void applyCentralPushImpulse(const btVector3& impulse)
+ {
+ m_pushVelocity += impulse * m_linearFactor * m_inverseMass;
+ }
+
+ void applyTorqueTurnImpulse(const btVector3& torque)
+ {
+ m_turnVelocity += m_invInertiaTensorWorld * torque * m_angularFactor;
+ }
void clearForces()
{
diff --git a/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBody.cpp b/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBody.cpp
index 3e210d7520..bdaa473476 100644
--- a/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBody.cpp
+++ b/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBody.cpp
@@ -100,6 +100,8 @@ btMultiBody::btMultiBody(int n_links,
m_baseName(0),
m_basePos(0, 0, 0),
m_baseQuat(0, 0, 0, 1),
+ m_basePos_interpolate(0, 0, 0),
+ m_baseQuat_interpolate(0, 0, 0, 1),
m_baseMass(mass),
m_baseInertia(inertia),
@@ -449,6 +451,16 @@ const btQuaternion &btMultiBody::getParentToLocalRot(int i) const
return m_links[i].m_cachedRotParentToThis;
}
+const btVector3 &btMultiBody::getInterpolateRVector(int i) const
+{
+ return m_links[i].m_cachedRVector_interpolate;
+}
+
+const btQuaternion &btMultiBody::getInterpolateParentToLocalRot(int i) const
+{
+ return m_links[i].m_cachedRotParentToThis_interpolate;
+}
+
btVector3 btMultiBody::localPosToWorld(int i, const btVector3 &local_pos) const
{
btAssert(i >= -1);
@@ -1581,6 +1593,158 @@ void btMultiBody::calcAccelerationDeltasMultiDof(const btScalar *force, btScalar
//printf("]\n");
/////////////////
}
+void btMultiBody::predictPositionsMultiDof(btScalar dt)
+{
+ int num_links = getNumLinks();
+ // step position by adding dt * velocity
+ //btVector3 v = getBaseVel();
+ //m_basePos += dt * v;
+ //
+ btScalar *pBasePos;
+ btScalar *pBaseVel = &m_realBuf[3]; //note: the !pqd case assumes m_realBuf holds with base velocity at 3,4,5 (should be wrapped for safety)
+
+ // reset to current position
+ for (int i = 0; i < 3; ++i)
+ {
+ m_basePos_interpolate[i] = m_basePos[i];
+ }
+ pBasePos = m_basePos_interpolate;
+
+ pBasePos[0] += dt * pBaseVel[0];
+ pBasePos[1] += dt * pBaseVel[1];
+ pBasePos[2] += dt * pBaseVel[2];
+
+ ///////////////////////////////
+ //local functor for quaternion integration (to avoid error prone redundancy)
+ struct
+ {
+ //"exponential map" based on btTransformUtil::integrateTransform(..)
+ void operator()(const btVector3 &omega, btQuaternion &quat, bool baseBody, btScalar dt)
+ {
+ //baseBody => quat is alias and omega is global coor
+ //!baseBody => quat is alibi and omega is local coor
+
+ btVector3 axis;
+ btVector3 angvel;
+
+ if (!baseBody)
+ angvel = quatRotate(quat, omega); //if quat is not m_baseQuat, it is alibi => ok
+ else
+ angvel = omega;
+
+ btScalar fAngle = angvel.length();
+ //limit the angular motion
+ if (fAngle * dt > ANGULAR_MOTION_THRESHOLD)
+ {
+ fAngle = btScalar(0.5) * SIMD_HALF_PI / dt;
+ }
+
+ if (fAngle < btScalar(0.001))
+ {
+ // use Taylor's expansions of sync function
+ axis = angvel * (btScalar(0.5) * dt - (dt * dt * dt) * (btScalar(0.020833333333)) * fAngle * fAngle);
+ }
+ else
+ {
+ // sync(fAngle) = sin(c*fAngle)/t
+ axis = angvel * (btSin(btScalar(0.5) * fAngle * dt) / fAngle);
+ }
+
+ if (!baseBody)
+ quat = btQuaternion(axis.x(), axis.y(), axis.z(), btCos(fAngle * dt * btScalar(0.5))) * quat;
+ else
+ quat = quat * btQuaternion(-axis.x(), -axis.y(), -axis.z(), btCos(fAngle * dt * btScalar(0.5)));
+ //equivalent to: quat = (btQuaternion(axis.x(),axis.y(),axis.z(),btCos( fAngle*dt*btScalar(0.5) )) * quat.inverse()).inverse();
+
+ quat.normalize();
+ }
+ } pQuatUpdateFun;
+ ///////////////////////////////
+
+ //pQuatUpdateFun(getBaseOmega(), m_baseQuat, true, dt);
+ //
+ btScalar *pBaseQuat;
+
+ // reset to current orientation
+ for (int i = 0; i < 4; ++i)
+ {
+ m_baseQuat_interpolate[i] = m_baseQuat[i];
+ }
+ pBaseQuat = m_baseQuat_interpolate;
+
+ btScalar *pBaseOmega = &m_realBuf[0]; //note: the !pqd case assumes m_realBuf starts with base omega (should be wrapped for safety)
+ //
+ btQuaternion baseQuat;
+ baseQuat.setValue(pBaseQuat[0], pBaseQuat[1], pBaseQuat[2], pBaseQuat[3]);
+ btVector3 baseOmega;
+ baseOmega.setValue(pBaseOmega[0], pBaseOmega[1], pBaseOmega[2]);
+ pQuatUpdateFun(baseOmega, baseQuat, true, dt);
+ pBaseQuat[0] = baseQuat.x();
+ pBaseQuat[1] = baseQuat.y();
+ pBaseQuat[2] = baseQuat.z();
+ pBaseQuat[3] = baseQuat.w();
+
+ // Finally we can update m_jointPos for each of the m_links
+ for (int i = 0; i < num_links; ++i)
+ {
+ btScalar *pJointPos;
+ pJointPos = &m_links[i].m_jointPos_interpolate[0];
+
+ btScalar *pJointVel = getJointVelMultiDof(i);
+
+ switch (m_links[i].m_jointType)
+ {
+ case btMultibodyLink::ePrismatic:
+ case btMultibodyLink::eRevolute:
+ {
+ //reset to current pos
+ pJointPos[0] = m_links[i].m_jointPos[0];
+ btScalar jointVel = pJointVel[0];
+ pJointPos[0] += dt * jointVel;
+ break;
+ }
+ case btMultibodyLink::eSpherical:
+ {
+ //reset to current pos
+
+ for (int j = 0; j < 4; ++j)
+ {
+ pJointPos[j] = m_links[i].m_jointPos[j];
+ }
+
+ btVector3 jointVel;
+ jointVel.setValue(pJointVel[0], pJointVel[1], pJointVel[2]);
+ btQuaternion jointOri;
+ jointOri.setValue(pJointPos[0], pJointPos[1], pJointPos[2], pJointPos[3]);
+ pQuatUpdateFun(jointVel, jointOri, false, dt);
+ pJointPos[0] = jointOri.x();
+ pJointPos[1] = jointOri.y();
+ pJointPos[2] = jointOri.z();
+ pJointPos[3] = jointOri.w();
+ break;
+ }
+ case btMultibodyLink::ePlanar:
+ {
+ for (int j = 0; j < 3; ++j)
+ {
+ pJointPos[j] = m_links[i].m_jointPos[j];
+ }
+ pJointPos[0] += dt * getJointVelMultiDof(i)[0];
+
+ btVector3 q0_coors_qd1qd2 = getJointVelMultiDof(i)[1] * m_links[i].getAxisBottom(1) + getJointVelMultiDof(i)[2] * m_links[i].getAxisBottom(2);
+ btVector3 no_q0_coors_qd1qd2 = quatRotate(btQuaternion(m_links[i].getAxisTop(0), pJointPos[0]), q0_coors_qd1qd2);
+ pJointPos[1] += m_links[i].getAxisBottom(1).dot(no_q0_coors_qd1qd2) * dt;
+ pJointPos[2] += m_links[i].getAxisBottom(2).dot(no_q0_coors_qd1qd2) * dt;
+ break;
+ }
+ default:
+ {
+ }
+ }
+
+ m_links[i].updateInterpolationCacheMultiDof();
+ }
+}
void btMultiBody::stepPositionsMultiDof(btScalar dt, btScalar *pq, btScalar *pqd)
{
@@ -1589,9 +1753,9 @@ void btMultiBody::stepPositionsMultiDof(btScalar dt, btScalar *pq, btScalar *pqd
//btVector3 v = getBaseVel();
//m_basePos += dt * v;
//
- btScalar *pBasePos = (pq ? &pq[4] : m_basePos);
- btScalar *pBaseVel = (pqd ? &pqd[3] : &m_realBuf[3]); //note: the !pqd case assumes m_realBuf holds with base velocity at 3,4,5 (should be wrapped for safety)
- //
+ btScalar *pBasePos = (pq ? &pq[4] : m_basePos);
+ btScalar *pBaseVel = (pqd ? &pqd[3] : &m_realBuf[3]); //note: the !pqd case assumes m_realBuf holds with base velocity at 3,4,5 (should be wrapped for safety)
+
pBasePos[0] += dt * pBaseVel[0];
pBasePos[1] += dt * pBaseVel[1];
pBasePos[2] += dt * pBaseVel[2];
@@ -1645,7 +1809,7 @@ void btMultiBody::stepPositionsMultiDof(btScalar dt, btScalar *pq, btScalar *pqd
//pQuatUpdateFun(getBaseOmega(), m_baseQuat, true, dt);
//
- btScalar *pBaseQuat = pq ? pq : m_baseQuat;
+ btScalar *pBaseQuat = pq ? pq : m_baseQuat;
btScalar *pBaseOmega = pqd ? pqd : &m_realBuf[0]; //note: the !pqd case assumes m_realBuf starts with base omega (should be wrapped for safety)
//
btQuaternion baseQuat;
@@ -1670,7 +1834,9 @@ void btMultiBody::stepPositionsMultiDof(btScalar dt, btScalar *pq, btScalar *pqd
// Finally we can update m_jointPos for each of the m_links
for (int i = 0; i < num_links; ++i)
{
- btScalar *pJointPos = (pq ? pq : &m_links[i].m_jointPos[0]);
+ btScalar *pJointPos;
+ pJointPos= (pq ? pq : &m_links[i].m_jointPos[0]);
+
btScalar *pJointVel = (pqd ? pqd : getJointVelMultiDof(i));
switch (m_links[i].m_jointType)
@@ -1678,12 +1844,14 @@ void btMultiBody::stepPositionsMultiDof(btScalar dt, btScalar *pq, btScalar *pqd
case btMultibodyLink::ePrismatic:
case btMultibodyLink::eRevolute:
{
+ //reset to current pos
btScalar jointVel = pJointVel[0];
pJointPos[0] += dt * jointVel;
break;
}
case btMultibodyLink::eSpherical:
{
+ //reset to current pos
btVector3 jointVel;
jointVel.setValue(pJointVel[0], pJointVel[1], pJointVel[2]);
btQuaternion jointOri;
@@ -1974,6 +2142,7 @@ void btMultiBody::updateCollisionObjectWorldTransforms(btAlignedObjectArray<btQu
tr.setRotation(btQuaternion(quat[0], quat[1], quat[2], quat[3]));
getBaseCollider()->setWorldTransform(tr);
+ getBaseCollider()->setInterpolationWorldTransform(tr);
}
for (int k = 0; k < getNumLinks(); k++)
@@ -2002,10 +2171,62 @@ void btMultiBody::updateCollisionObjectWorldTransforms(btAlignedObjectArray<btQu
tr.setRotation(btQuaternion(quat[0], quat[1], quat[2], quat[3]));
col->setWorldTransform(tr);
+ col->setInterpolationWorldTransform(tr);
}
}
}
+void btMultiBody::updateCollisionObjectInterpolationWorldTransforms(btAlignedObjectArray<btQuaternion> &world_to_local, btAlignedObjectArray<btVector3> &local_origin)
+{
+ world_to_local.resize(getNumLinks() + 1);
+ local_origin.resize(getNumLinks() + 1);
+
+ world_to_local[0] = getInterpolateWorldToBaseRot();
+ local_origin[0] = getInterpolateBasePos();
+
+ if (getBaseCollider())
+ {
+ btVector3 posr = local_origin[0];
+ // float pos[4]={posr.x(),posr.y(),posr.z(),1};
+ btScalar quat[4] = {-world_to_local[0].x(), -world_to_local[0].y(), -world_to_local[0].z(), world_to_local[0].w()};
+ btTransform tr;
+ tr.setIdentity();
+ tr.setOrigin(posr);
+ tr.setRotation(btQuaternion(quat[0], quat[1], quat[2], quat[3]));
+
+ getBaseCollider()->setInterpolationWorldTransform(tr);
+ }
+
+ for (int k = 0; k < getNumLinks(); k++)
+ {
+ const int parent = getParent(k);
+ world_to_local[k + 1] = getInterpolateParentToLocalRot(k) * world_to_local[parent + 1];
+ local_origin[k + 1] = local_origin[parent + 1] + (quatRotate(world_to_local[k + 1].inverse(), getInterpolateRVector(k)));
+ }
+
+ for (int m = 0; m < getNumLinks(); m++)
+ {
+ btMultiBodyLinkCollider *col = getLink(m).m_collider;
+ if (col)
+ {
+ int link = col->m_link;
+ btAssert(link == m);
+
+ int index = link + 1;
+
+ btVector3 posr = local_origin[index];
+ // float pos[4]={posr.x(),posr.y(),posr.z(),1};
+ btScalar quat[4] = {-world_to_local[index].x(), -world_to_local[index].y(), -world_to_local[index].z(), world_to_local[index].w()};
+ btTransform tr;
+ tr.setIdentity();
+ tr.setOrigin(posr);
+ tr.setRotation(btQuaternion(quat[0], quat[1], quat[2], quat[3]));
+
+ col->setInterpolationWorldTransform(tr);
+ }
+ }
+}
+
int btMultiBody::calculateSerializeBufferSize() const
{
int sz = sizeof(btMultiBodyData);
diff --git a/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBody.h b/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBody.h
index c0b0d003be..afed669a7b 100644
--- a/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBody.h
+++ b/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBody.h
@@ -193,12 +193,24 @@ public:
const btQuaternion &getWorldToBaseRot() const
{
return m_baseQuat;
- } // rotates world vectors into base frame
+ }
+
+ const btVector3 &getInterpolateBasePos() const
+ {
+ return m_basePos_interpolate;
+ } // in world frame
+ const btQuaternion &getInterpolateWorldToBaseRot() const
+ {
+ return m_baseQuat_interpolate;
+ }
+
+ // rotates world vectors into base frame
btVector3 getBaseOmega() const { return btVector3(m_realBuf[0], m_realBuf[1], m_realBuf[2]); } // in world frame
void setBasePos(const btVector3 &pos)
{
m_basePos = pos;
+ m_basePos_interpolate = pos;
}
void setBaseWorldTransform(const btTransform &tr)
@@ -224,6 +236,7 @@ public:
void setWorldToBaseRot(const btQuaternion &rot)
{
m_baseQuat = rot; //m_baseQuat asumed to ba alias!?
+ m_baseQuat_interpolate = rot;
}
void setBaseOmega(const btVector3 &omega)
{
@@ -260,6 +273,11 @@ public:
{
return &m_realBuf[0];
}
+
+ const btScalar *getDeltaVelocityVector() const
+ {
+ return &m_deltaV[0];
+ }
/* btScalar * getVelocityVector()
{
return &real_buf[0];
@@ -273,6 +291,8 @@ public:
const btVector3 &getRVector(int i) const; // vector from COM(parent(i)) to COM(i), in frame i's coords
const btQuaternion &getParentToLocalRot(int i) const; // rotates vectors in frame parent(i) to vectors in frame i.
+ const btVector3 &getInterpolateRVector(int i) const; // vector from COM(parent(i)) to COM(i), in frame i's coords
+ const btQuaternion &getInterpolateParentToLocalRot(int i) const; // rotates vectors in frame parent(i) to vectors in frame i.
//
// transform vectors in local frame of link i to world frame (or vice versa)
@@ -421,6 +441,9 @@ public:
// timestep the positions (given current velocities).
void stepPositionsMultiDof(btScalar dt, btScalar *pq = 0, btScalar *pqd = 0);
+
+ // predict the positions
+ void predictPositionsMultiDof(btScalar dt);
//
// contacts
@@ -581,6 +604,7 @@ public:
void compTreeLinkVelocities(btVector3 * omega, btVector3 * vel) const;
void updateCollisionObjectWorldTransforms(btAlignedObjectArray<btQuaternion> & world_to_local, btAlignedObjectArray<btVector3> & local_origin);
+ void updateCollisionObjectInterpolationWorldTransforms(btAlignedObjectArray<btQuaternion> & world_to_local, btAlignedObjectArray<btVector3> & local_origin);
virtual int calculateSerializeBufferSize() const;
@@ -664,7 +688,9 @@ private:
const char *m_baseName; //memory needs to be manager by user!
btVector3 m_basePos; // position of COM of base (world frame)
+ btVector3 m_basePos_interpolate; // position of interpolated COM of base (world frame)
btQuaternion m_baseQuat; // rotates world points into base frame
+ btQuaternion m_baseQuat_interpolate;
btScalar m_baseMass; // mass of the base
btVector3 m_baseInertia; // inertia of the base (in local frame; diagonal)
diff --git a/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyConstraint.cpp b/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyConstraint.cpp
index e17ab94d98..d7ed05ce57 100644
--- a/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyConstraint.cpp
+++ b/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyConstraint.cpp
@@ -342,40 +342,6 @@ btScalar btMultiBodyConstraint::fillMultiBodyConstraint(btMultiBodySolverConstra
solverConstraint.m_friction = 0.f; //cp.m_combinedFriction;
}
- ///warm starting (or zero if disabled)
- /*
- if (infoGlobal.m_solverMode & SOLVER_USE_WARMSTARTING)
- {
- solverConstraint.m_appliedImpulse = isFriction ? 0 : cp.m_appliedImpulse * infoGlobal.m_warmstartingFactor;
-
- if (solverConstraint.m_appliedImpulse)
- {
- if (multiBodyA)
- {
- btScalar impulse = solverConstraint.m_appliedImpulse;
- btScalar* deltaV = &data.m_deltaVelocitiesUnitImpulse[solverConstraint.m_jacAindex];
- multiBodyA->applyDeltaVee(deltaV,impulse);
- applyDeltaVee(data,deltaV,impulse,solverConstraint.m_deltaVelAindex,ndofA);
- } else
- {
- if (rb0)
- bodyA->internalApplyImpulse(solverConstraint.m_contactNormal1*bodyA->internalGetInvMass()*rb0->getLinearFactor(),solverConstraint.m_angularComponentA,solverConstraint.m_appliedImpulse);
- }
- if (multiBodyB)
- {
- btScalar impulse = solverConstraint.m_appliedImpulse;
- btScalar* deltaV = &data.m_deltaVelocitiesUnitImpulse[solverConstraint.m_jacBindex];
- multiBodyB->applyDeltaVee(deltaV,impulse);
- applyDeltaVee(data,deltaV,impulse,solverConstraint.m_deltaVelBindex,ndofB);
- } else
- {
- if (rb1)
- bodyB->internalApplyImpulse(-solverConstraint.m_contactNormal2*bodyB->internalGetInvMass()*rb1->getLinearFactor(),-solverConstraint.m_angularComponentB,-(btScalar)solverConstraint.m_appliedImpulse);
- }
- }
- } else
- */
-
solverConstraint.m_appliedImpulse = 0.f;
solverConstraint.m_appliedPushImpulse = 0.f;
diff --git a/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyConstraintSolver.cpp b/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyConstraintSolver.cpp
index 23e163f0e8..ffae5300f0 100644
--- a/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyConstraintSolver.cpp
+++ b/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyConstraintSolver.cpp
@@ -22,6 +22,8 @@ subject to the following restrictions:
#include "BulletDynamics/ConstraintSolver/btContactSolverInfo.h"
#include "LinearMath/btQuickprof.h"
+#include "BulletDynamics/Featherstone/btMultiBodySolverConstraint.h"
+#include "LinearMath/btScalar.h"
btScalar btMultiBodyConstraintSolver::solveSingleIteration(int iteration, btCollisionObject** bodies, int numBodies, btPersistentManifold** manifoldPtr, int numManifolds, btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& infoGlobal, btIDebugDraw* debugDrawer)
{
@@ -491,11 +493,7 @@ btScalar btMultiBodyConstraintSolver::resolveConeFrictionConstraintRows(const bt
return deltaVel;
}
-void btMultiBodyConstraintSolver::setupMultiBodyContactConstraint(btMultiBodySolverConstraint& solverConstraint,
- const btVector3& contactNormal,
- btManifoldPoint& cp, const btContactSolverInfo& infoGlobal,
- btScalar& relaxation,
- bool isFriction, btScalar desiredVelocity, btScalar cfmSlip)
+void btMultiBodyConstraintSolver::setupMultiBodyContactConstraint(btMultiBodySolverConstraint& solverConstraint, const btVector3& contactNormal, const btScalar& appliedImpulse, btManifoldPoint& cp, const btContactSolverInfo& infoGlobal, btScalar& relaxation, bool isFriction, btScalar desiredVelocity, btScalar cfmSlip)
{
BT_PROFILE("setupMultiBodyContactConstraint");
btVector3 rel_pos1;
@@ -781,48 +779,6 @@ void btMultiBodyConstraintSolver::setupMultiBodyContactConstraint(btMultiBodySol
}
}
- ///warm starting (or zero if disabled)
- //disable warmstarting for btMultiBody, it has issues gaining energy (==explosion)
- if (0) //infoGlobal.m_solverMode & SOLVER_USE_WARMSTARTING)
- {
- solverConstraint.m_appliedImpulse = isFriction ? 0 : cp.m_appliedImpulse * infoGlobal.m_warmstartingFactor;
-
- if (solverConstraint.m_appliedImpulse)
- {
- if (multiBodyA)
- {
- btScalar impulse = solverConstraint.m_appliedImpulse;
- btScalar* deltaV = &m_data.m_deltaVelocitiesUnitImpulse[solverConstraint.m_jacAindex];
- multiBodyA->applyDeltaVeeMultiDof(deltaV, impulse);
-
- applyDeltaVee(deltaV, impulse, solverConstraint.m_deltaVelAindex, ndofA);
- }
- else
- {
- if (rb0)
- bodyA->internalApplyImpulse(solverConstraint.m_contactNormal1 * bodyA->internalGetInvMass() * rb0->getLinearFactor(), solverConstraint.m_angularComponentA, solverConstraint.m_appliedImpulse);
- }
- if (multiBodyB)
- {
- btScalar impulse = solverConstraint.m_appliedImpulse;
- btScalar* deltaV = &m_data.m_deltaVelocitiesUnitImpulse[solverConstraint.m_jacBindex];
- multiBodyB->applyDeltaVeeMultiDof(deltaV, impulse);
- applyDeltaVee(deltaV, impulse, solverConstraint.m_deltaVelBindex, ndofB);
- }
- else
- {
- if (rb1)
- bodyB->internalApplyImpulse(-solverConstraint.m_contactNormal2 * bodyB->internalGetInvMass() * rb1->getLinearFactor(), -solverConstraint.m_angularComponentB, -(btScalar)solverConstraint.m_appliedImpulse);
- }
- }
- }
- else
- {
- solverConstraint.m_appliedImpulse = 0.f;
- }
-
- solverConstraint.m_appliedPushImpulse = 0.f;
-
{
btScalar positionalError = 0.f;
btScalar velocityError = restitution - rel_vel; // * damping; //note for friction restitution is always set to 0 (check above) so it is acutally velocityError = -rel_vel for friction
@@ -874,6 +830,54 @@ void btMultiBodyConstraintSolver::setupMultiBodyContactConstraint(btMultiBodySol
solverConstraint.m_cfm = cfm * solverConstraint.m_jacDiagABInv;
}
+
+ if (infoGlobal.m_solverMode & SOLVER_USE_ARTICULATED_WARMSTARTING)
+ {
+ if (btFabs(cp.m_prevRHS) > 1e-5 && cp.m_prevRHS < 2* solverConstraint.m_rhs && solverConstraint.m_rhs < 2*cp.m_prevRHS)
+ {
+ solverConstraint.m_appliedImpulse = isFriction ? 0 : cp.m_appliedImpulse / cp.m_prevRHS * solverConstraint.m_rhs * infoGlobal.m_articulatedWarmstartingFactor;
+ if (solverConstraint.m_appliedImpulse < 0)
+ solverConstraint.m_appliedImpulse = 0;
+ }
+ else
+ {
+ solverConstraint.m_appliedImpulse = 0.f;
+ }
+
+ if (solverConstraint.m_appliedImpulse)
+ {
+ if (multiBodyA)
+ {
+ btScalar impulse = solverConstraint.m_appliedImpulse;
+ btScalar* deltaV = &m_data.m_deltaVelocitiesUnitImpulse[solverConstraint.m_jacAindex];
+ multiBodyA->applyDeltaVeeMultiDof2(deltaV, impulse);
+
+ applyDeltaVee(deltaV, impulse, solverConstraint.m_deltaVelAindex, ndofA);
+ }
+ else
+ {
+ if (rb0)
+ bodyA->internalApplyImpulse(solverConstraint.m_contactNormal1 * bodyA->internalGetInvMass() * rb0->getLinearFactor(), solverConstraint.m_angularComponentA, solverConstraint.m_appliedImpulse);
+ }
+ if (multiBodyB)
+ {
+ btScalar impulse = solverConstraint.m_appliedImpulse;
+ btScalar* deltaV = &m_data.m_deltaVelocitiesUnitImpulse[solverConstraint.m_jacBindex];
+ multiBodyB->applyDeltaVeeMultiDof2(deltaV, impulse);
+ applyDeltaVee(deltaV, impulse, solverConstraint.m_deltaVelBindex, ndofB);
+ }
+ else
+ {
+ if (rb1)
+ bodyB->internalApplyImpulse(-solverConstraint.m_contactNormal2 * bodyB->internalGetInvMass() * rb1->getLinearFactor(), -solverConstraint.m_angularComponentB, -(btScalar)solverConstraint.m_appliedImpulse);
+ }
+ }
+ }
+ else
+ {
+ solverConstraint.m_appliedImpulse = 0.f;
+ solverConstraint.m_appliedPushImpulse = 0.f;
+ }
}
void btMultiBodyConstraintSolver::setupMultiBodyTorsionalFrictionConstraint(btMultiBodySolverConstraint& solverConstraint,
@@ -944,13 +948,13 @@ void btMultiBodyConstraintSolver::setupMultiBodyTorsionalFrictionConstraint(btMu
btScalar* delta = &m_data.m_deltaVelocitiesUnitImpulse[solverConstraint.m_jacAindex];
multiBodyA->calcAccelerationDeltasMultiDof(&m_data.m_jacobians[solverConstraint.m_jacAindex], delta, m_data.scratch_r, m_data.scratch_v);
- btVector3 torqueAxis0 = -constraintNormal;
+ btVector3 torqueAxis0 = constraintNormal;
solverConstraint.m_relpos1CrossNormal = torqueAxis0;
solverConstraint.m_contactNormal1 = btVector3(0, 0, 0);
}
else
{
- btVector3 torqueAxis0 = -constraintNormal;
+ btVector3 torqueAxis0 = constraintNormal;
solverConstraint.m_relpos1CrossNormal = torqueAxis0;
solverConstraint.m_contactNormal1 = btVector3(0, 0, 0);
solverConstraint.m_angularComponentA = rb0 ? rb0->getInvInertiaTensorWorld() * torqueAxis0 * rb0->getAngularFactor() : btVector3(0, 0, 0);
@@ -986,13 +990,13 @@ void btMultiBodyConstraintSolver::setupMultiBodyTorsionalFrictionConstraint(btMu
multiBodyB->fillConstraintJacobianMultiDof(solverConstraint.m_linkB, cp.getPositionWorldOnB(), -constraintNormal, btVector3(0, 0, 0), &m_data.m_jacobians[solverConstraint.m_jacBindex], m_data.scratch_r, m_data.scratch_v, m_data.scratch_m);
multiBodyB->calcAccelerationDeltasMultiDof(&m_data.m_jacobians[solverConstraint.m_jacBindex], &m_data.m_deltaVelocitiesUnitImpulse[solverConstraint.m_jacBindex], m_data.scratch_r, m_data.scratch_v);
- btVector3 torqueAxis1 = constraintNormal;
+ btVector3 torqueAxis1 = -constraintNormal;
solverConstraint.m_relpos2CrossNormal = torqueAxis1;
solverConstraint.m_contactNormal2 = -btVector3(0, 0, 0);
}
else
{
- btVector3 torqueAxis1 = constraintNormal;
+ btVector3 torqueAxis1 = -constraintNormal;
solverConstraint.m_relpos2CrossNormal = torqueAxis1;
solverConstraint.m_contactNormal2 = -btVector3(0, 0, 0);
@@ -1130,7 +1134,7 @@ void btMultiBodyConstraintSolver::setupMultiBodyTorsionalFrictionConstraint(btMu
}
}
-btMultiBodySolverConstraint& btMultiBodyConstraintSolver::addMultiBodyFrictionConstraint(const btVector3& normalAxis, btPersistentManifold* manifold, int frictionIndex, btManifoldPoint& cp, btCollisionObject* colObj0, btCollisionObject* colObj1, btScalar relaxation, const btContactSolverInfo& infoGlobal, btScalar desiredVelocity, btScalar cfmSlip)
+btMultiBodySolverConstraint& btMultiBodyConstraintSolver::addMultiBodyFrictionConstraint(const btVector3& normalAxis, const btScalar& appliedImpulse, btPersistentManifold* manifold, int frictionIndex, btManifoldPoint& cp, btCollisionObject* colObj0, btCollisionObject* colObj1, btScalar relaxation, const btContactSolverInfo& infoGlobal, btScalar desiredVelocity, btScalar cfmSlip)
{
BT_PROFILE("addMultiBodyFrictionConstraint");
btMultiBodySolverConstraint& solverConstraint = m_multiBodyFrictionContactConstraints.expandNonInitializing();
@@ -1161,7 +1165,7 @@ btMultiBodySolverConstraint& btMultiBodyConstraintSolver::addMultiBodyFrictionCo
solverConstraint.m_originalContactPoint = &cp;
- setupMultiBodyContactConstraint(solverConstraint, normalAxis, cp, infoGlobal, relaxation, isFriction, desiredVelocity, cfmSlip);
+ setupMultiBodyContactConstraint(solverConstraint, normalAxis, 0, cp, infoGlobal, relaxation, isFriction, desiredVelocity, cfmSlip);
return solverConstraint;
}
@@ -1297,7 +1301,7 @@ void btMultiBodyConstraintSolver::convertMultiBodyContact(btPersistentManifold*
solverConstraint.m_originalContactPoint = &cp;
bool isFriction = false;
- setupMultiBodyContactConstraint(solverConstraint, cp.m_normalWorldOnB, cp, infoGlobal, relaxation, isFriction);
+ setupMultiBodyContactConstraint(solverConstraint, cp.m_normalWorldOnB, cp.m_appliedImpulse, cp, infoGlobal, relaxation, isFriction);
// const btVector3& pos1 = cp.getPositionWorldOnA();
// const btVector3& pos2 = cp.getPositionWorldOnB();
@@ -1371,13 +1375,13 @@ void btMultiBodyConstraintSolver::convertMultiBodyContact(btPersistentManifold*
{
applyAnisotropicFriction(colObj0, cp.m_lateralFrictionDir1, btCollisionObject::CF_ANISOTROPIC_FRICTION);
applyAnisotropicFriction(colObj1, cp.m_lateralFrictionDir1, btCollisionObject::CF_ANISOTROPIC_FRICTION);
- addMultiBodyFrictionConstraint(cp.m_lateralFrictionDir1, manifold, frictionIndex, cp, colObj0, colObj1, relaxation, infoGlobal);
+ addMultiBodyFrictionConstraint(cp.m_lateralFrictionDir1, cp.m_appliedImpulseLateral1, manifold, frictionIndex, cp, colObj0, colObj1, relaxation, infoGlobal);
if ((infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS))
{
applyAnisotropicFriction(colObj0, cp.m_lateralFrictionDir2, btCollisionObject::CF_ANISOTROPIC_FRICTION);
applyAnisotropicFriction(colObj1, cp.m_lateralFrictionDir2, btCollisionObject::CF_ANISOTROPIC_FRICTION);
- addMultiBodyFrictionConstraint(cp.m_lateralFrictionDir2, manifold, frictionIndex, cp, colObj0, colObj1, relaxation, infoGlobal);
+ addMultiBodyFrictionConstraint(cp.m_lateralFrictionDir2, cp.m_appliedImpulseLateral2, manifold, frictionIndex, cp, colObj0, colObj1, relaxation, infoGlobal);
}
if ((infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS) && (infoGlobal.m_solverMode & SOLVER_DISABLE_VELOCITY_DEPENDENT_FRICTION_DIRECTION))
@@ -1388,26 +1392,27 @@ void btMultiBodyConstraintSolver::convertMultiBodyContact(btPersistentManifold*
}
else
{
- addMultiBodyFrictionConstraint(cp.m_lateralFrictionDir1, manifold, frictionIndex, cp, colObj0, colObj1, relaxation, infoGlobal, cp.m_contactMotion1, cp.m_frictionCFM);
+ addMultiBodyFrictionConstraint(cp.m_lateralFrictionDir1, cp.m_appliedImpulseLateral1, manifold, frictionIndex, cp, colObj0, colObj1, relaxation, infoGlobal, cp.m_contactMotion1, cp.m_frictionCFM);
if ((infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS))
- addMultiBodyFrictionConstraint(cp.m_lateralFrictionDir2, manifold, frictionIndex, cp, colObj0, colObj1, relaxation, infoGlobal, cp.m_contactMotion2, cp.m_frictionCFM);
-
- //setMultiBodyFrictionConstraintImpulse( solverConstraint, solverBodyIdA, solverBodyIdB, cp, infoGlobal);
- //todo:
+ addMultiBodyFrictionConstraint(cp.m_lateralFrictionDir2, cp.m_appliedImpulseLateral2, manifold, frictionIndex, cp, colObj0, colObj1, relaxation, infoGlobal, cp.m_contactMotion2, cp.m_frictionCFM);
solverConstraint.m_appliedImpulse = 0.f;
solverConstraint.m_appliedPushImpulse = 0.f;
- }
+ }
#endif //ENABLE_FRICTION
}
+ else
+ {
+ // Reset quantities related to warmstart as 0.
+ cp.m_appliedImpulse = 0;
+ cp.m_prevRHS = 0;
+ }
}
}
void btMultiBodyConstraintSolver::convertContacts(btPersistentManifold** manifoldPtr, int numManifolds, const btContactSolverInfo& infoGlobal)
{
- //btPersistentManifold* manifold = 0;
-
for (int i = 0; i < numManifolds; i++)
{
btPersistentManifold* manifold = manifoldPtr[i];
@@ -1434,6 +1439,51 @@ void btMultiBodyConstraintSolver::convertContacts(btPersistentManifold** manifol
c->createConstraintRows(m_multiBodyNonContactConstraints, m_data, infoGlobal);
}
+
+ // Warmstart for noncontact constraints
+ if (infoGlobal.m_solverMode & SOLVER_USE_ARTICULATED_WARMSTARTING)
+ {
+ for (int i = 0; i < m_multiBodyNonContactConstraints.size(); i++)
+ {
+ btMultiBodySolverConstraint& solverConstraint =
+ m_multiBodyNonContactConstraints[i];
+ solverConstraint.m_appliedImpulse =
+ solverConstraint.m_orgConstraint->getAppliedImpulse(solverConstraint.m_orgDofIndex) *
+ infoGlobal.m_articulatedWarmstartingFactor;
+
+ btMultiBody* multiBodyA = solverConstraint.m_multiBodyA;
+ btMultiBody* multiBodyB = solverConstraint.m_multiBodyB;
+ if (solverConstraint.m_appliedImpulse)
+ {
+ if (multiBodyA)
+ {
+ int ndofA = multiBodyA->getNumDofs() + 6;
+ btScalar* deltaV =
+ &m_data.m_deltaVelocitiesUnitImpulse[solverConstraint.m_jacAindex];
+ btScalar impulse = solverConstraint.m_appliedImpulse;
+ multiBodyA->applyDeltaVeeMultiDof2(deltaV, impulse);
+ applyDeltaVee(deltaV, impulse, solverConstraint.m_deltaVelAindex, ndofA);
+ }
+ if (multiBodyB)
+ {
+ int ndofB = multiBodyB->getNumDofs() + 6;
+ btScalar* deltaV =
+ &m_data.m_deltaVelocitiesUnitImpulse[solverConstraint.m_jacBindex];
+ btScalar impulse = solverConstraint.m_appliedImpulse;
+ multiBodyB->applyDeltaVeeMultiDof2(deltaV, impulse);
+ applyDeltaVee(deltaV, impulse, solverConstraint.m_deltaVelBindex, ndofB);
+ }
+ }
+ }
+ }
+ else
+ {
+ for (int i = 0; i < m_multiBodyNonContactConstraints.size(); i++)
+ {
+ btMultiBodySolverConstraint& solverConstraint = m_multiBodyNonContactConstraints[i];
+ solverConstraint.m_appliedImpulse = 0;
+ }
+ }
}
btScalar btMultiBodyConstraintSolver::solveGroup(btCollisionObject** bodies, int numBodies, btPersistentManifold** manifold, int numManifolds, btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& info, btIDebugDraw* debugDrawer, btDispatcher* dispatcher)
@@ -1556,7 +1606,7 @@ btScalar btMultiBodyConstraintSolver::solveGroupCacheFriendlyFinish(btCollisionO
writeBackSolverBodyToMultiBody(solverConstraint, infoGlobal.m_timeStep);
}
- if (infoGlobal.m_solverMode & SOLVER_USE_WARMSTARTING)
+
{
BT_PROFILE("warm starting write back");
for (int j = 0; j < numPoolConstraints; j++)
@@ -1565,6 +1615,7 @@ btScalar btMultiBodyConstraintSolver::solveGroupCacheFriendlyFinish(btCollisionO
btManifoldPoint* pt = (btManifoldPoint*)solverConstraint.m_originalContactPoint;
btAssert(pt);
pt->m_appliedImpulse = solverConstraint.m_appliedImpulse;
+ pt->m_prevRHS = solverConstraint.m_rhs;
pt->m_appliedImpulseLateral1 = m_multiBodyFrictionContactConstraints[solverConstraint.m_frictionIndex].m_appliedImpulse;
//printf("pt->m_appliedImpulseLateral1 = %f\n", pt->m_appliedImpulseLateral1);
@@ -1576,9 +1627,8 @@ btScalar btMultiBodyConstraintSolver::solveGroupCacheFriendlyFinish(btCollisionO
pt->m_appliedImpulseLateral2 = 0;
}
}
-
- //do a callback here?
}
+
#if 0
//multibody joint feedback
{
diff --git a/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyConstraintSolver.h b/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyConstraintSolver.h
index abf5718839..f584360e2b 100644
--- a/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyConstraintSolver.h
+++ b/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyConstraintSolver.h
@@ -49,7 +49,7 @@ protected:
void convertContacts(btPersistentManifold * *manifoldPtr, int numManifolds, const btContactSolverInfo& infoGlobal);
- btMultiBodySolverConstraint& addMultiBodyFrictionConstraint(const btVector3& normalAxis, btPersistentManifold* manifold, int frictionIndex, btManifoldPoint& cp, btCollisionObject* colObj0, btCollisionObject* colObj1, btScalar relaxation, const btContactSolverInfo& infoGlobal, btScalar desiredVelocity = 0, btScalar cfmSlip = 0);
+ btMultiBodySolverConstraint& addMultiBodyFrictionConstraint(const btVector3& normalAxis, const btScalar& appliedImpulse, btPersistentManifold* manifold, int frictionIndex, btManifoldPoint& cp, btCollisionObject* colObj0, btCollisionObject* colObj1, btScalar relaxation, const btContactSolverInfo& infoGlobal, btScalar desiredVelocity = 0, btScalar cfmSlip = 0);
btMultiBodySolverConstraint& addMultiBodyTorsionalFrictionConstraint(const btVector3& normalAxis, btPersistentManifold* manifold, int frictionIndex, btManifoldPoint& cp,
btScalar combinedTorsionalFriction,
@@ -66,7 +66,9 @@ protected:
void setupMultiBodyContactConstraint(btMultiBodySolverConstraint & solverConstraint,
const btVector3& contactNormal,
- btManifoldPoint& cp, const btContactSolverInfo& infoGlobal,
+ const btScalar& appliedImpulse,
+ btManifoldPoint& cp,
+ const btContactSolverInfo& infoGlobal,
btScalar& relaxation,
bool isFriction, btScalar desiredVelocity = 0, btScalar cfmSlip = 0);
@@ -82,7 +84,6 @@ protected:
void convertMultiBodyContact(btPersistentManifold * manifold, const btContactSolverInfo& infoGlobal);
virtual btScalar solveGroupCacheFriendlySetup(btCollisionObject * *bodies, int numBodies, btPersistentManifold** manifoldPtr, int numManifolds, btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& infoGlobal, btIDebugDraw* debugDrawer);
// virtual btScalar solveGroupCacheFriendlyIterations(btCollisionObject** bodies,int numBodies,btPersistentManifold** manifoldPtr, int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& infoGlobal,btIDebugDraw* debugDrawer);
-
virtual btScalar solveSingleIteration(int iteration, btCollisionObject** bodies, int numBodies, btPersistentManifold** manifoldPtr, int numManifolds, btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& infoGlobal, btIDebugDraw* debugDrawer);
void applyDeltaVee(btScalar * deltaV, btScalar impulse, int velocityIndex, int ndof);
void writeBackSolverBodyToMultiBody(btMultiBodySolverConstraint & constraint, btScalar deltaTime);
diff --git a/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyDynamicsWorld.cpp b/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyDynamicsWorld.cpp
index 1131e5378c..cd1bad089e 100644
--- a/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyDynamicsWorld.cpp
+++ b/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyDynamicsWorld.cpp
@@ -33,6 +33,12 @@ void btMultiBodyDynamicsWorld::removeMultiBody(btMultiBody* body)
m_multiBodies.remove(body);
}
+void btMultiBodyDynamicsWorld::predictUnconstraintMotion(btScalar timeStep)
+{
+ btDiscreteDynamicsWorld::predictUnconstraintMotion(timeStep);
+ predictMultiBodyTransforms(timeStep);
+
+}
void btMultiBodyDynamicsWorld::calculateSimulationIslands()
{
BT_PROFILE("calculateSimulationIslands");
@@ -163,218 +169,6 @@ void btMultiBodyDynamicsWorld::updateActivationState(btScalar timeStep)
btDiscreteDynamicsWorld::updateActivationState(timeStep);
}
-SIMD_FORCE_INLINE int btGetConstraintIslandId2(const btTypedConstraint* lhs)
-{
- int islandId;
-
- const btCollisionObject& rcolObj0 = lhs->getRigidBodyA();
- const btCollisionObject& rcolObj1 = lhs->getRigidBodyB();
- islandId = rcolObj0.getIslandTag() >= 0 ? rcolObj0.getIslandTag() : rcolObj1.getIslandTag();
- return islandId;
-}
-
-class btSortConstraintOnIslandPredicate2
-{
-public:
- bool operator()(const btTypedConstraint* lhs, const btTypedConstraint* rhs) const
- {
- int rIslandId0, lIslandId0;
- rIslandId0 = btGetConstraintIslandId2(rhs);
- lIslandId0 = btGetConstraintIslandId2(lhs);
- return lIslandId0 < rIslandId0;
- }
-};
-
-SIMD_FORCE_INLINE int btGetMultiBodyConstraintIslandId(const btMultiBodyConstraint* lhs)
-{
- int islandId;
-
- int islandTagA = lhs->getIslandIdA();
- int islandTagB = lhs->getIslandIdB();
- islandId = islandTagA >= 0 ? islandTagA : islandTagB;
- return islandId;
-}
-
-class btSortMultiBodyConstraintOnIslandPredicate
-{
-public:
- bool operator()(const btMultiBodyConstraint* lhs, const btMultiBodyConstraint* rhs) const
- {
- int rIslandId0, lIslandId0;
- rIslandId0 = btGetMultiBodyConstraintIslandId(rhs);
- lIslandId0 = btGetMultiBodyConstraintIslandId(lhs);
- return lIslandId0 < rIslandId0;
- }
-};
-
-
-struct MultiBodyInplaceSolverIslandCallback : public btSimulationIslandManager::IslandCallback
-{
- btContactSolverInfo* m_solverInfo;
- btMultiBodyConstraintSolver* m_solver;
- btMultiBodyConstraint** m_multiBodySortedConstraints;
- int m_numMultiBodyConstraints;
-
- btTypedConstraint** m_sortedConstraints;
- int m_numConstraints;
- btIDebugDraw* m_debugDrawer;
- btDispatcher* m_dispatcher;
-
- btAlignedObjectArray<btCollisionObject*> m_bodies;
- btAlignedObjectArray<btPersistentManifold*> m_manifolds;
- btAlignedObjectArray<btTypedConstraint*> m_constraints;
- btAlignedObjectArray<btMultiBodyConstraint*> m_multiBodyConstraints;
-
- btAlignedObjectArray<btSolverAnalyticsData> m_islandAnalyticsData;
-
- MultiBodyInplaceSolverIslandCallback(btMultiBodyConstraintSolver* solver,
- btDispatcher* dispatcher)
- : m_solverInfo(NULL),
- m_solver(solver),
- m_multiBodySortedConstraints(NULL),
- m_numConstraints(0),
- m_debugDrawer(NULL),
- m_dispatcher(dispatcher)
- {
- }
-
- MultiBodyInplaceSolverIslandCallback& operator=(const MultiBodyInplaceSolverIslandCallback& other)
- {
- btAssert(0);
- (void)other;
- return *this;
- }
-
- SIMD_FORCE_INLINE void setup(btContactSolverInfo* solverInfo, btTypedConstraint** sortedConstraints, int numConstraints, btMultiBodyConstraint** sortedMultiBodyConstraints, int numMultiBodyConstraints, btIDebugDraw* debugDrawer)
- {
- m_islandAnalyticsData.clear();
- btAssert(solverInfo);
- m_solverInfo = solverInfo;
-
- m_multiBodySortedConstraints = sortedMultiBodyConstraints;
- m_numMultiBodyConstraints = numMultiBodyConstraints;
- m_sortedConstraints = sortedConstraints;
- m_numConstraints = numConstraints;
-
- m_debugDrawer = debugDrawer;
- m_bodies.resize(0);
- m_manifolds.resize(0);
- m_constraints.resize(0);
- m_multiBodyConstraints.resize(0);
- }
-
- void setMultiBodyConstraintSolver(btMultiBodyConstraintSolver* solver)
- {
- m_solver = solver;
- }
-
- virtual void processIsland(btCollisionObject** bodies, int numBodies, btPersistentManifold** manifolds, int numManifolds, int islandId)
- {
- if (islandId < 0)
- {
- ///we don't split islands, so all constraints/contact manifolds/bodies are passed into the solver regardless the island id
- m_solver->solveMultiBodyGroup(bodies, numBodies, manifolds, numManifolds, m_sortedConstraints, m_numConstraints, &m_multiBodySortedConstraints[0], m_numConstraints, *m_solverInfo, m_debugDrawer, m_dispatcher);
- if (m_solverInfo->m_reportSolverAnalytics&1)
- {
- m_solver->m_analyticsData.m_islandId = islandId;
- m_islandAnalyticsData.push_back(m_solver->m_analyticsData);
- }
- }
- else
- {
- //also add all non-contact constraints/joints for this island
- btTypedConstraint** startConstraint = 0;
- btMultiBodyConstraint** startMultiBodyConstraint = 0;
-
- int numCurConstraints = 0;
- int numCurMultiBodyConstraints = 0;
-
- int i;
-
- //find the first constraint for this island
-
- for (i = 0; i < m_numConstraints; i++)
- {
- if (btGetConstraintIslandId2(m_sortedConstraints[i]) == islandId)
- {
- startConstraint = &m_sortedConstraints[i];
- break;
- }
- }
- //count the number of constraints in this island
- for (; i < m_numConstraints; i++)
- {
- if (btGetConstraintIslandId2(m_sortedConstraints[i]) == islandId)
- {
- numCurConstraints++;
- }
- }
-
- for (i = 0; i < m_numMultiBodyConstraints; i++)
- {
- if (btGetMultiBodyConstraintIslandId(m_multiBodySortedConstraints[i]) == islandId)
- {
- startMultiBodyConstraint = &m_multiBodySortedConstraints[i];
- break;
- }
- }
- //count the number of multi body constraints in this island
- for (; i < m_numMultiBodyConstraints; i++)
- {
- if (btGetMultiBodyConstraintIslandId(m_multiBodySortedConstraints[i]) == islandId)
- {
- numCurMultiBodyConstraints++;
- }
- }
-
- //if (m_solverInfo->m_minimumSolverBatchSize<=1)
- //{
- // m_solver->solveGroup( bodies,numBodies,manifolds, numManifolds,startConstraint,numCurConstraints,*m_solverInfo,m_debugDrawer,m_dispatcher);
- //} else
- {
- for (i = 0; i < numBodies; i++)
- m_bodies.push_back(bodies[i]);
- for (i = 0; i < numManifolds; i++)
- m_manifolds.push_back(manifolds[i]);
- for (i = 0; i < numCurConstraints; i++)
- m_constraints.push_back(startConstraint[i]);
-
- for (i = 0; i < numCurMultiBodyConstraints; i++)
- m_multiBodyConstraints.push_back(startMultiBodyConstraint[i]);
-
- if ((m_multiBodyConstraints.size() + m_constraints.size() + m_manifolds.size()) > m_solverInfo->m_minimumSolverBatchSize)
- {
- processConstraints(islandId);
- }
- else
- {
- //printf("deferred\n");
- }
- }
- }
- }
- void processConstraints(int islandId=-1)
- {
- btCollisionObject** bodies = m_bodies.size() ? &m_bodies[0] : 0;
- btPersistentManifold** manifold = m_manifolds.size() ? &m_manifolds[0] : 0;
- btTypedConstraint** constraints = m_constraints.size() ? &m_constraints[0] : 0;
- btMultiBodyConstraint** multiBodyConstraints = m_multiBodyConstraints.size() ? &m_multiBodyConstraints[0] : 0;
-
- //printf("mb contacts = %d, mb constraints = %d\n", mbContacts, m_multiBodyConstraints.size());
-
- m_solver->solveMultiBodyGroup(bodies, m_bodies.size(), manifold, m_manifolds.size(), constraints, m_constraints.size(), multiBodyConstraints, m_multiBodyConstraints.size(), *m_solverInfo, m_debugDrawer, m_dispatcher);
- if (m_bodies.size() && (m_solverInfo->m_reportSolverAnalytics&1))
- {
- m_solver->m_analyticsData.m_islandId = islandId;
- m_islandAnalyticsData.push_back(m_solver->m_analyticsData);
- }
- m_bodies.resize(0);
- m_manifolds.resize(0);
- m_constraints.resize(0);
- m_multiBodyConstraints.resize(0);
- }
-};
-
void btMultiBodyDynamicsWorld::getAnalyticsData(btAlignedObjectArray<btSolverAnalyticsData>& islandAnalyticsData) const
{
islandAnalyticsData = m_solverMultiBodyIslandCallback->m_islandAnalyticsData;
@@ -421,350 +215,364 @@ void btMultiBodyDynamicsWorld::forwardKinematics()
}
void btMultiBodyDynamicsWorld::solveConstraints(btContactSolverInfo& solverInfo)
{
- forwardKinematics();
-
- BT_PROFILE("solveConstraints");
-
- clearMultiBodyConstraintForces();
-
- m_sortedConstraints.resize(m_constraints.size());
- int i;
- for (i = 0; i < getNumConstraints(); i++)
- {
- m_sortedConstraints[i] = m_constraints[i];
- }
- m_sortedConstraints.quickSort(btSortConstraintOnIslandPredicate2());
- btTypedConstraint** constraintsPtr = getNumConstraints() ? &m_sortedConstraints[0] : 0;
-
- m_sortedMultiBodyConstraints.resize(m_multiBodyConstraints.size());
- for (i = 0; i < m_multiBodyConstraints.size(); i++)
- {
- m_sortedMultiBodyConstraints[i] = m_multiBodyConstraints[i];
- }
- m_sortedMultiBodyConstraints.quickSort(btSortMultiBodyConstraintOnIslandPredicate());
+ solveExternalForces(solverInfo);
+ buildIslands();
+ solveInternalConstraints(solverInfo);
+}
- btMultiBodyConstraint** sortedMultiBodyConstraints = m_sortedMultiBodyConstraints.size() ? &m_sortedMultiBodyConstraints[0] : 0;
+void btMultiBodyDynamicsWorld::buildIslands()
+{
+ m_islandManager->buildAndProcessIslands(getCollisionWorld()->getDispatcher(), getCollisionWorld(), m_solverMultiBodyIslandCallback);
+}
- m_solverMultiBodyIslandCallback->setup(&solverInfo, constraintsPtr, m_sortedConstraints.size(), sortedMultiBodyConstraints, m_sortedMultiBodyConstraints.size(), getDebugDrawer());
- m_constraintSolver->prepareSolve(getCollisionWorld()->getNumCollisionObjects(), getCollisionWorld()->getDispatcher()->getNumManifolds());
+void btMultiBodyDynamicsWorld::solveInternalConstraints(btContactSolverInfo& solverInfo)
+{
+ /// solve all the constraints for this island
+ m_solverMultiBodyIslandCallback->processConstraints();
+ m_constraintSolver->allSolved(solverInfo, m_debugDrawer);
+ {
+ BT_PROFILE("btMultiBody stepVelocities");
+ for (int i = 0; i < this->m_multiBodies.size(); i++)
+ {
+ btMultiBody* bod = m_multiBodies[i];
+
+ bool isSleeping = false;
+
+ if (bod->getBaseCollider() && bod->getBaseCollider()->getActivationState() == ISLAND_SLEEPING)
+ {
+ isSleeping = true;
+ }
+ for (int b = 0; b < bod->getNumLinks(); b++)
+ {
+ if (bod->getLink(b).m_collider && bod->getLink(b).m_collider->getActivationState() == ISLAND_SLEEPING)
+ isSleeping = true;
+ }
+
+ if (!isSleeping)
+ {
+ //useless? they get resized in stepVelocities once again (AND DIFFERENTLY)
+ m_scratch_r.resize(bod->getNumLinks() + 1); //multidof? ("Y"s use it and it is used to store qdd)
+ m_scratch_v.resize(bod->getNumLinks() + 1);
+ m_scratch_m.resize(bod->getNumLinks() + 1);
+
+ if (bod->internalNeedsJointFeedback())
+ {
+ if (!bod->isUsingRK4Integration())
+ {
+ if (bod->internalNeedsJointFeedback())
+ {
+ bool isConstraintPass = true;
+ bod->computeAccelerationsArticulatedBodyAlgorithmMultiDof(solverInfo.m_timeStep, m_scratch_r, m_scratch_v, m_scratch_m, isConstraintPass,
+ getSolverInfo().m_jointFeedbackInWorldSpace,
+ getSolverInfo().m_jointFeedbackInJointFrame);
+ }
+ }
+ }
+ }
+ }
+ }
+ for (int i = 0; i < this->m_multiBodies.size(); i++)
+ {
+ btMultiBody* bod = m_multiBodies[i];
+ bod->processDeltaVeeMultiDof2();
+ }
+}
+void btMultiBodyDynamicsWorld::solveExternalForces(btContactSolverInfo& solverInfo)
+{
+ forwardKinematics();
+
+ BT_PROFILE("solveConstraints");
+
+ clearMultiBodyConstraintForces();
+
+ m_sortedConstraints.resize(m_constraints.size());
+ int i;
+ for (i = 0; i < getNumConstraints(); i++)
+ {
+ m_sortedConstraints[i] = m_constraints[i];
+ }
+ m_sortedConstraints.quickSort(btSortConstraintOnIslandPredicate2());
+ btTypedConstraint** constraintsPtr = getNumConstraints() ? &m_sortedConstraints[0] : 0;
+
+ m_sortedMultiBodyConstraints.resize(m_multiBodyConstraints.size());
+ for (i = 0; i < m_multiBodyConstraints.size(); i++)
+ {
+ m_sortedMultiBodyConstraints[i] = m_multiBodyConstraints[i];
+ }
+ m_sortedMultiBodyConstraints.quickSort(btSortMultiBodyConstraintOnIslandPredicate());
+
+ btMultiBodyConstraint** sortedMultiBodyConstraints = m_sortedMultiBodyConstraints.size() ? &m_sortedMultiBodyConstraints[0] : 0;
+
+ m_solverMultiBodyIslandCallback->setup(&solverInfo, constraintsPtr, m_sortedConstraints.size(), sortedMultiBodyConstraints, m_sortedMultiBodyConstraints.size(), getDebugDrawer());
+ m_constraintSolver->prepareSolve(getCollisionWorld()->getNumCollisionObjects(), getCollisionWorld()->getDispatcher()->getNumManifolds());
+
#ifndef BT_USE_VIRTUAL_CLEARFORCES_AND_GRAVITY
- {
- BT_PROFILE("btMultiBody addForce");
- for (int i = 0; i < this->m_multiBodies.size(); i++)
- {
- btMultiBody* bod = m_multiBodies[i];
-
- bool isSleeping = false;
-
- if (bod->getBaseCollider() && bod->getBaseCollider()->getActivationState() == ISLAND_SLEEPING)
- {
- isSleeping = true;
- }
- for (int b = 0; b < bod->getNumLinks(); b++)
- {
- if (bod->getLink(b).m_collider && bod->getLink(b).m_collider->getActivationState() == ISLAND_SLEEPING)
- isSleeping = true;
- }
-
- if (!isSleeping)
- {
- //useless? they get resized in stepVelocities once again (AND DIFFERENTLY)
- m_scratch_r.resize(bod->getNumLinks() + 1); //multidof? ("Y"s use it and it is used to store qdd)
- m_scratch_v.resize(bod->getNumLinks() + 1);
- m_scratch_m.resize(bod->getNumLinks() + 1);
-
- bod->addBaseForce(m_gravity * bod->getBaseMass());
-
- for (int j = 0; j < bod->getNumLinks(); ++j)
- {
- bod->addLinkForce(j, m_gravity * bod->getLinkMass(j));
- }
- } //if (!isSleeping)
- }
- }
+ {
+ BT_PROFILE("btMultiBody addForce");
+ for (int i = 0; i < this->m_multiBodies.size(); i++)
+ {
+ btMultiBody* bod = m_multiBodies[i];
+
+ bool isSleeping = false;
+
+ if (bod->getBaseCollider() && bod->getBaseCollider()->getActivationState() == ISLAND_SLEEPING)
+ {
+ isSleeping = true;
+ }
+ for (int b = 0; b < bod->getNumLinks(); b++)
+ {
+ if (bod->getLink(b).m_collider && bod->getLink(b).m_collider->getActivationState() == ISLAND_SLEEPING)
+ isSleeping = true;
+ }
+
+ if (!isSleeping)
+ {
+ //useless? they get resized in stepVelocities once again (AND DIFFERENTLY)
+ m_scratch_r.resize(bod->getNumLinks() + 1); //multidof? ("Y"s use it and it is used to store qdd)
+ m_scratch_v.resize(bod->getNumLinks() + 1);
+ m_scratch_m.resize(bod->getNumLinks() + 1);
+
+ bod->addBaseForce(m_gravity * bod->getBaseMass());
+
+ for (int j = 0; j < bod->getNumLinks(); ++j)
+ {
+ bod->addLinkForce(j, m_gravity * bod->getLinkMass(j));
+ }
+ } //if (!isSleeping)
+ }
+ }
#endif //BT_USE_VIRTUAL_CLEARFORCES_AND_GRAVITY
-
- {
- BT_PROFILE("btMultiBody stepVelocities");
- for (int i = 0; i < this->m_multiBodies.size(); i++)
- {
- btMultiBody* bod = m_multiBodies[i];
-
- bool isSleeping = false;
-
- if (bod->getBaseCollider() && bod->getBaseCollider()->getActivationState() == ISLAND_SLEEPING)
- {
- isSleeping = true;
- }
- for (int b = 0; b < bod->getNumLinks(); b++)
- {
- if (bod->getLink(b).m_collider && bod->getLink(b).m_collider->getActivationState() == ISLAND_SLEEPING)
- isSleeping = true;
- }
-
- if (!isSleeping)
- {
- //useless? they get resized in stepVelocities once again (AND DIFFERENTLY)
- m_scratch_r.resize(bod->getNumLinks() + 1); //multidof? ("Y"s use it and it is used to store qdd)
- m_scratch_v.resize(bod->getNumLinks() + 1);
- m_scratch_m.resize(bod->getNumLinks() + 1);
- bool doNotUpdatePos = false;
+
+ {
+ BT_PROFILE("btMultiBody stepVelocities");
+ for (int i = 0; i < this->m_multiBodies.size(); i++)
+ {
+ btMultiBody* bod = m_multiBodies[i];
+
+ bool isSleeping = false;
+
+ if (bod->getBaseCollider() && bod->getBaseCollider()->getActivationState() == ISLAND_SLEEPING)
+ {
+ isSleeping = true;
+ }
+ for (int b = 0; b < bod->getNumLinks(); b++)
+ {
+ if (bod->getLink(b).m_collider && bod->getLink(b).m_collider->getActivationState() == ISLAND_SLEEPING)
+ isSleeping = true;
+ }
+
+ if (!isSleeping)
+ {
+ //useless? they get resized in stepVelocities once again (AND DIFFERENTLY)
+ m_scratch_r.resize(bod->getNumLinks() + 1); //multidof? ("Y"s use it and it is used to store qdd)
+ m_scratch_v.resize(bod->getNumLinks() + 1);
+ m_scratch_m.resize(bod->getNumLinks() + 1);
+ bool doNotUpdatePos = false;
bool isConstraintPass = false;
- {
- if (!bod->isUsingRK4Integration())
- {
- bod->computeAccelerationsArticulatedBodyAlgorithmMultiDof(solverInfo.m_timeStep,
- m_scratch_r, m_scratch_v, m_scratch_m,isConstraintPass,
- getSolverInfo().m_jointFeedbackInWorldSpace,
- getSolverInfo().m_jointFeedbackInJointFrame);
- }
- else
- {
- //
- int numDofs = bod->getNumDofs() + 6;
- int numPosVars = bod->getNumPosVars() + 7;
- btAlignedObjectArray<btScalar> scratch_r2;
- scratch_r2.resize(2 * numPosVars + 8 * numDofs);
- //convenience
- btScalar* pMem = &scratch_r2[0];
- btScalar* scratch_q0 = pMem;
- pMem += numPosVars;
- btScalar* scratch_qx = pMem;
- pMem += numPosVars;
- btScalar* scratch_qd0 = pMem;
- pMem += numDofs;
- btScalar* scratch_qd1 = pMem;
- pMem += numDofs;
- btScalar* scratch_qd2 = pMem;
- pMem += numDofs;
- btScalar* scratch_qd3 = pMem;
- pMem += numDofs;
- btScalar* scratch_qdd0 = pMem;
- pMem += numDofs;
- btScalar* scratch_qdd1 = pMem;
- pMem += numDofs;
- btScalar* scratch_qdd2 = pMem;
- pMem += numDofs;
- btScalar* scratch_qdd3 = pMem;
- pMem += numDofs;
- btAssert((pMem - (2 * numPosVars + 8 * numDofs)) == &scratch_r2[0]);
-
- /////
- //copy q0 to scratch_q0 and qd0 to scratch_qd0
- scratch_q0[0] = bod->getWorldToBaseRot().x();
- scratch_q0[1] = bod->getWorldToBaseRot().y();
- scratch_q0[2] = bod->getWorldToBaseRot().z();
- scratch_q0[3] = bod->getWorldToBaseRot().w();
- scratch_q0[4] = bod->getBasePos().x();
- scratch_q0[5] = bod->getBasePos().y();
- scratch_q0[6] = bod->getBasePos().z();
- //
- for (int link = 0; link < bod->getNumLinks(); ++link)
- {
- for (int dof = 0; dof < bod->getLink(link).m_posVarCount; ++dof)
- scratch_q0[7 + bod->getLink(link).m_cfgOffset + dof] = bod->getLink(link).m_jointPos[dof];
- }
- //
- for (int dof = 0; dof < numDofs; ++dof)
- scratch_qd0[dof] = bod->getVelocityVector()[dof];
- ////
- struct
- {
- btMultiBody* bod;
- btScalar *scratch_qx, *scratch_q0;
-
- void operator()()
- {
- for (int dof = 0; dof < bod->getNumPosVars() + 7; ++dof)
- scratch_qx[dof] = scratch_q0[dof];
- }
- } pResetQx = {bod, scratch_qx, scratch_q0};
- //
- struct
- {
- void operator()(btScalar dt, const btScalar* pDer, const btScalar* pCurVal, btScalar* pVal, int size)
- {
- for (int i = 0; i < size; ++i)
- pVal[i] = pCurVal[i] + dt * pDer[i];
- }
-
- } pEulerIntegrate;
- //
- struct
- {
- void operator()(btMultiBody* pBody, const btScalar* pData)
- {
- btScalar* pVel = const_cast<btScalar*>(pBody->getVelocityVector());
-
- for (int i = 0; i < pBody->getNumDofs() + 6; ++i)
- pVel[i] = pData[i];
- }
- } pCopyToVelocityVector;
- //
- struct
- {
- void operator()(const btScalar* pSrc, btScalar* pDst, int start, int size)
- {
- for (int i = 0; i < size; ++i)
- pDst[i] = pSrc[start + i];
- }
- } pCopy;
- //
-
- btScalar h = solverInfo.m_timeStep;
+ {
+ if (!bod->isUsingRK4Integration())
+ {
+ bod->computeAccelerationsArticulatedBodyAlgorithmMultiDof(solverInfo.m_timeStep,
+ m_scratch_r, m_scratch_v, m_scratch_m,isConstraintPass,
+ getSolverInfo().m_jointFeedbackInWorldSpace,
+ getSolverInfo().m_jointFeedbackInJointFrame);
+ }
+ else
+ {
+ //
+ int numDofs = bod->getNumDofs() + 6;
+ int numPosVars = bod->getNumPosVars() + 7;
+ btAlignedObjectArray<btScalar> scratch_r2;
+ scratch_r2.resize(2 * numPosVars + 8 * numDofs);
+ //convenience
+ btScalar* pMem = &scratch_r2[0];
+ btScalar* scratch_q0 = pMem;
+ pMem += numPosVars;
+ btScalar* scratch_qx = pMem;
+ pMem += numPosVars;
+ btScalar* scratch_qd0 = pMem;
+ pMem += numDofs;
+ btScalar* scratch_qd1 = pMem;
+ pMem += numDofs;
+ btScalar* scratch_qd2 = pMem;
+ pMem += numDofs;
+ btScalar* scratch_qd3 = pMem;
+ pMem += numDofs;
+ btScalar* scratch_qdd0 = pMem;
+ pMem += numDofs;
+ btScalar* scratch_qdd1 = pMem;
+ pMem += numDofs;
+ btScalar* scratch_qdd2 = pMem;
+ pMem += numDofs;
+ btScalar* scratch_qdd3 = pMem;
+ pMem += numDofs;
+ btAssert((pMem - (2 * numPosVars + 8 * numDofs)) == &scratch_r2[0]);
+
+ /////
+ //copy q0 to scratch_q0 and qd0 to scratch_qd0
+ scratch_q0[0] = bod->getWorldToBaseRot().x();
+ scratch_q0[1] = bod->getWorldToBaseRot().y();
+ scratch_q0[2] = bod->getWorldToBaseRot().z();
+ scratch_q0[3] = bod->getWorldToBaseRot().w();
+ scratch_q0[4] = bod->getBasePos().x();
+ scratch_q0[5] = bod->getBasePos().y();
+ scratch_q0[6] = bod->getBasePos().z();
+ //
+ for (int link = 0; link < bod->getNumLinks(); ++link)
+ {
+ for (int dof = 0; dof < bod->getLink(link).m_posVarCount; ++dof)
+ scratch_q0[7 + bod->getLink(link).m_cfgOffset + dof] = bod->getLink(link).m_jointPos[dof];
+ }
+ //
+ for (int dof = 0; dof < numDofs; ++dof)
+ scratch_qd0[dof] = bod->getVelocityVector()[dof];
+ ////
+ struct
+ {
+ btMultiBody* bod;
+ btScalar *scratch_qx, *scratch_q0;
+
+ void operator()()
+ {
+ for (int dof = 0; dof < bod->getNumPosVars() + 7; ++dof)
+ scratch_qx[dof] = scratch_q0[dof];
+ }
+ } pResetQx = {bod, scratch_qx, scratch_q0};
+ //
+ struct
+ {
+ void operator()(btScalar dt, const btScalar* pDer, const btScalar* pCurVal, btScalar* pVal, int size)
+ {
+ for (int i = 0; i < size; ++i)
+ pVal[i] = pCurVal[i] + dt * pDer[i];
+ }
+
+ } pEulerIntegrate;
+ //
+ struct
+ {
+ void operator()(btMultiBody* pBody, const btScalar* pData)
+ {
+ btScalar* pVel = const_cast<btScalar*>(pBody->getVelocityVector());
+
+ for (int i = 0; i < pBody->getNumDofs() + 6; ++i)
+ pVel[i] = pData[i];
+ }
+ } pCopyToVelocityVector;
+ //
+ struct
+ {
+ void operator()(const btScalar* pSrc, btScalar* pDst, int start, int size)
+ {
+ for (int i = 0; i < size; ++i)
+ pDst[i] = pSrc[start + i];
+ }
+ } pCopy;
+ //
+
+ btScalar h = solverInfo.m_timeStep;
#define output &m_scratch_r[bod->getNumDofs()]
- //calc qdd0 from: q0 & qd0
- bod->computeAccelerationsArticulatedBodyAlgorithmMultiDof(0., m_scratch_r, m_scratch_v, m_scratch_m,
- isConstraintPass,getSolverInfo().m_jointFeedbackInWorldSpace,
- getSolverInfo().m_jointFeedbackInJointFrame);
- pCopy(output, scratch_qdd0, 0, numDofs);
- //calc q1 = q0 + h/2 * qd0
- pResetQx();
- bod->stepPositionsMultiDof(btScalar(.5) * h, scratch_qx, scratch_qd0);
- //calc qd1 = qd0 + h/2 * qdd0
- pEulerIntegrate(btScalar(.5) * h, scratch_qdd0, scratch_qd0, scratch_qd1, numDofs);
- //
- //calc qdd1 from: q1 & qd1
- pCopyToVelocityVector(bod, scratch_qd1);
- bod->computeAccelerationsArticulatedBodyAlgorithmMultiDof(0., m_scratch_r, m_scratch_v, m_scratch_m,
- isConstraintPass,getSolverInfo().m_jointFeedbackInWorldSpace,
- getSolverInfo().m_jointFeedbackInJointFrame);
- pCopy(output, scratch_qdd1, 0, numDofs);
- //calc q2 = q0 + h/2 * qd1
- pResetQx();
- bod->stepPositionsMultiDof(btScalar(.5) * h, scratch_qx, scratch_qd1);
- //calc qd2 = qd0 + h/2 * qdd1
- pEulerIntegrate(btScalar(.5) * h, scratch_qdd1, scratch_qd0, scratch_qd2, numDofs);
- //
- //calc qdd2 from: q2 & qd2
- pCopyToVelocityVector(bod, scratch_qd2);
- bod->computeAccelerationsArticulatedBodyAlgorithmMultiDof(0., m_scratch_r, m_scratch_v, m_scratch_m,
- isConstraintPass,getSolverInfo().m_jointFeedbackInWorldSpace,
- getSolverInfo().m_jointFeedbackInJointFrame);
- pCopy(output, scratch_qdd2, 0, numDofs);
- //calc q3 = q0 + h * qd2
- pResetQx();
- bod->stepPositionsMultiDof(h, scratch_qx, scratch_qd2);
- //calc qd3 = qd0 + h * qdd2
- pEulerIntegrate(h, scratch_qdd2, scratch_qd0, scratch_qd3, numDofs);
- //
- //calc qdd3 from: q3 & qd3
- pCopyToVelocityVector(bod, scratch_qd3);
- bod->computeAccelerationsArticulatedBodyAlgorithmMultiDof(0., m_scratch_r, m_scratch_v, m_scratch_m,
- isConstraintPass,getSolverInfo().m_jointFeedbackInWorldSpace,
- getSolverInfo().m_jointFeedbackInJointFrame);
- pCopy(output, scratch_qdd3, 0, numDofs);
-
- //
- //calc q = q0 + h/6(qd0 + 2*(qd1 + qd2) + qd3)
- //calc qd = qd0 + h/6(qdd0 + 2*(qdd1 + qdd2) + qdd3)
- btAlignedObjectArray<btScalar> delta_q;
- delta_q.resize(numDofs);
- btAlignedObjectArray<btScalar> delta_qd;
- delta_qd.resize(numDofs);
- for (int i = 0; i < numDofs; ++i)
- {
- delta_q[i] = h / btScalar(6.) * (scratch_qd0[i] + 2 * scratch_qd1[i] + 2 * scratch_qd2[i] + scratch_qd3[i]);
- delta_qd[i] = h / btScalar(6.) * (scratch_qdd0[i] + 2 * scratch_qdd1[i] + 2 * scratch_qdd2[i] + scratch_qdd3[i]);
- //delta_q[i] = h*scratch_qd0[i];
- //delta_qd[i] = h*scratch_qdd0[i];
- }
- //
- pCopyToVelocityVector(bod, scratch_qd0);
- bod->applyDeltaVeeMultiDof(&delta_qd[0], 1);
- //
- if (!doNotUpdatePos)
- {
- btScalar* pRealBuf = const_cast<btScalar*>(bod->getVelocityVector());
- pRealBuf += 6 + bod->getNumDofs() + bod->getNumDofs() * bod->getNumDofs();
-
- for (int i = 0; i < numDofs; ++i)
- pRealBuf[i] = delta_q[i];
-
- //bod->stepPositionsMultiDof(1, 0, &delta_q[0]);
- bod->setPosUpdated(true);
- }
-
- //ugly hack which resets the cached data to t0 (needed for constraint solver)
- {
- for (int link = 0; link < bod->getNumLinks(); ++link)
- bod->getLink(link).updateCacheMultiDof();
- bod->computeAccelerationsArticulatedBodyAlgorithmMultiDof(0, m_scratch_r, m_scratch_v, m_scratch_m,
- isConstraintPass,getSolverInfo().m_jointFeedbackInWorldSpace,
- getSolverInfo().m_jointFeedbackInJointFrame);
- }
- }
- }
-
+ //calc qdd0 from: q0 & qd0
+ bod->computeAccelerationsArticulatedBodyAlgorithmMultiDof(0., m_scratch_r, m_scratch_v, m_scratch_m,
+ isConstraintPass,getSolverInfo().m_jointFeedbackInWorldSpace,
+ getSolverInfo().m_jointFeedbackInJointFrame);
+ pCopy(output, scratch_qdd0, 0, numDofs);
+ //calc q1 = q0 + h/2 * qd0
+ pResetQx();
+ bod->stepPositionsMultiDof(btScalar(.5) * h, scratch_qx, scratch_qd0);
+ //calc qd1 = qd0 + h/2 * qdd0
+ pEulerIntegrate(btScalar(.5) * h, scratch_qdd0, scratch_qd0, scratch_qd1, numDofs);
+ //
+ //calc qdd1 from: q1 & qd1
+ pCopyToVelocityVector(bod, scratch_qd1);
+ bod->computeAccelerationsArticulatedBodyAlgorithmMultiDof(0., m_scratch_r, m_scratch_v, m_scratch_m,
+ isConstraintPass,getSolverInfo().m_jointFeedbackInWorldSpace,
+ getSolverInfo().m_jointFeedbackInJointFrame);
+ pCopy(output, scratch_qdd1, 0, numDofs);
+ //calc q2 = q0 + h/2 * qd1
+ pResetQx();
+ bod->stepPositionsMultiDof(btScalar(.5) * h, scratch_qx, scratch_qd1);
+ //calc qd2 = qd0 + h/2 * qdd1
+ pEulerIntegrate(btScalar(.5) * h, scratch_qdd1, scratch_qd0, scratch_qd2, numDofs);
+ //
+ //calc qdd2 from: q2 & qd2
+ pCopyToVelocityVector(bod, scratch_qd2);
+ bod->computeAccelerationsArticulatedBodyAlgorithmMultiDof(0., m_scratch_r, m_scratch_v, m_scratch_m,
+ isConstraintPass,getSolverInfo().m_jointFeedbackInWorldSpace,
+ getSolverInfo().m_jointFeedbackInJointFrame);
+ pCopy(output, scratch_qdd2, 0, numDofs);
+ //calc q3 = q0 + h * qd2
+ pResetQx();
+ bod->stepPositionsMultiDof(h, scratch_qx, scratch_qd2);
+ //calc qd3 = qd0 + h * qdd2
+ pEulerIntegrate(h, scratch_qdd2, scratch_qd0, scratch_qd3, numDofs);
+ //
+ //calc qdd3 from: q3 & qd3
+ pCopyToVelocityVector(bod, scratch_qd3);
+ bod->computeAccelerationsArticulatedBodyAlgorithmMultiDof(0., m_scratch_r, m_scratch_v, m_scratch_m,
+ isConstraintPass,getSolverInfo().m_jointFeedbackInWorldSpace,
+ getSolverInfo().m_jointFeedbackInJointFrame);
+ pCopy(output, scratch_qdd3, 0, numDofs);
+
+ //
+ //calc q = q0 + h/6(qd0 + 2*(qd1 + qd2) + qd3)
+ //calc qd = qd0 + h/6(qdd0 + 2*(qdd1 + qdd2) + qdd3)
+ btAlignedObjectArray<btScalar> delta_q;
+ delta_q.resize(numDofs);
+ btAlignedObjectArray<btScalar> delta_qd;
+ delta_qd.resize(numDofs);
+ for (int i = 0; i < numDofs; ++i)
+ {
+ delta_q[i] = h / btScalar(6.) * (scratch_qd0[i] + 2 * scratch_qd1[i] + 2 * scratch_qd2[i] + scratch_qd3[i]);
+ delta_qd[i] = h / btScalar(6.) * (scratch_qdd0[i] + 2 * scratch_qdd1[i] + 2 * scratch_qdd2[i] + scratch_qdd3[i]);
+ //delta_q[i] = h*scratch_qd0[i];
+ //delta_qd[i] = h*scratch_qdd0[i];
+ }
+ //
+ pCopyToVelocityVector(bod, scratch_qd0);
+ bod->applyDeltaVeeMultiDof(&delta_qd[0], 1);
+ //
+ if (!doNotUpdatePos)
+ {
+ btScalar* pRealBuf = const_cast<btScalar*>(bod->getVelocityVector());
+ pRealBuf += 6 + bod->getNumDofs() + bod->getNumDofs() * bod->getNumDofs();
+
+ for (int i = 0; i < numDofs; ++i)
+ pRealBuf[i] = delta_q[i];
+
+ //bod->stepPositionsMultiDof(1, 0, &delta_q[0]);
+ bod->setPosUpdated(true);
+ }
+
+ //ugly hack which resets the cached data to t0 (needed for constraint solver)
+ {
+ for (int link = 0; link < bod->getNumLinks(); ++link)
+ bod->getLink(link).updateCacheMultiDof();
+ bod->computeAccelerationsArticulatedBodyAlgorithmMultiDof(0, m_scratch_r, m_scratch_v, m_scratch_m,
+ isConstraintPass,getSolverInfo().m_jointFeedbackInWorldSpace,
+ getSolverInfo().m_jointFeedbackInJointFrame);
+ }
+ }
+ }
+
#ifndef BT_USE_VIRTUAL_CLEARFORCES_AND_GRAVITY
- bod->clearForcesAndTorques();
+ bod->clearForcesAndTorques();
#endif //BT_USE_VIRTUAL_CLEARFORCES_AND_GRAVITY
- } //if (!isSleeping)
- }
- }
-
- /// solve all the constraints for this island
- m_islandManager->buildAndProcessIslands(getCollisionWorld()->getDispatcher(), getCollisionWorld(), m_solverMultiBodyIslandCallback);
-
- m_solverMultiBodyIslandCallback->processConstraints();
-
- m_constraintSolver->allSolved(solverInfo, m_debugDrawer);
-
- {
- BT_PROFILE("btMultiBody stepVelocities");
- for (int i = 0; i < this->m_multiBodies.size(); i++)
- {
- btMultiBody* bod = m_multiBodies[i];
-
- bool isSleeping = false;
-
- if (bod->getBaseCollider() && bod->getBaseCollider()->getActivationState() == ISLAND_SLEEPING)
- {
- isSleeping = true;
- }
- for (int b = 0; b < bod->getNumLinks(); b++)
- {
- if (bod->getLink(b).m_collider && bod->getLink(b).m_collider->getActivationState() == ISLAND_SLEEPING)
- isSleeping = true;
- }
-
- if (!isSleeping)
- {
- //useless? they get resized in stepVelocities once again (AND DIFFERENTLY)
- m_scratch_r.resize(bod->getNumLinks() + 1); //multidof? ("Y"s use it and it is used to store qdd)
- m_scratch_v.resize(bod->getNumLinks() + 1);
- m_scratch_m.resize(bod->getNumLinks() + 1);
-
- if (bod->internalNeedsJointFeedback())
- {
- if (!bod->isUsingRK4Integration())
- {
- if (bod->internalNeedsJointFeedback())
- {
- bool isConstraintPass = true;
- bod->computeAccelerationsArticulatedBodyAlgorithmMultiDof(solverInfo.m_timeStep, m_scratch_r, m_scratch_v, m_scratch_m, isConstraintPass,
- getSolverInfo().m_jointFeedbackInWorldSpace,
- getSolverInfo().m_jointFeedbackInJointFrame);
- }
- }
- }
- }
- }
- }
-
- for (int i = 0; i < this->m_multiBodies.size(); i++)
- {
- btMultiBody* bod = m_multiBodies[i];
- bod->processDeltaVeeMultiDof2();
- }
+ } //if (!isSleeping)
+ }
+ }
}
+
void btMultiBodyDynamicsWorld::integrateTransforms(btScalar timeStep)
{
btDiscreteDynamicsWorld::integrateTransforms(timeStep);
+ integrateMultiBodyTransforms(timeStep);
+}
- {
+void btMultiBodyDynamicsWorld::integrateMultiBodyTransforms(btScalar timeStep)
+{
BT_PROFILE("btMultiBody stepPositions");
//integrate and update the Featherstone hierarchies
@@ -787,31 +595,61 @@ void btMultiBodyDynamicsWorld::integrateTransforms(btScalar timeStep)
int nLinks = bod->getNumLinks();
///base + num m_links
+ if (!bod->isPosUpdated())
+ bod->stepPositionsMultiDof(timeStep);
+ else
+ {
+ btScalar* pRealBuf = const_cast<btScalar*>(bod->getVelocityVector());
+ pRealBuf += 6 + bod->getNumDofs() + bod->getNumDofs() * bod->getNumDofs();
- {
- if (!bod->isPosUpdated())
- bod->stepPositionsMultiDof(timeStep);
- else
- {
- btScalar* pRealBuf = const_cast<btScalar*>(bod->getVelocityVector());
- pRealBuf += 6 + bod->getNumDofs() + bod->getNumDofs() * bod->getNumDofs();
+ bod->stepPositionsMultiDof(1, 0, pRealBuf);
+ bod->setPosUpdated(false);
+ }
- bod->stepPositionsMultiDof(1, 0, pRealBuf);
- bod->setPosUpdated(false);
- }
- }
m_scratch_world_to_local.resize(nLinks + 1);
m_scratch_local_origin.resize(nLinks + 1);
-
- bod->updateCollisionObjectWorldTransforms(m_scratch_world_to_local, m_scratch_local_origin);
+ bod->updateCollisionObjectWorldTransforms(m_scratch_world_to_local, m_scratch_local_origin);
}
else
{
bod->clearVelocities();
}
}
- }
+}
+
+void btMultiBodyDynamicsWorld::predictMultiBodyTransforms(btScalar timeStep)
+{
+ BT_PROFILE("btMultiBody stepPositions");
+ //integrate and update the Featherstone hierarchies
+
+ for (int b = 0; b < m_multiBodies.size(); b++)
+ {
+ btMultiBody* bod = m_multiBodies[b];
+ bool isSleeping = false;
+ if (bod->getBaseCollider() && bod->getBaseCollider()->getActivationState() == ISLAND_SLEEPING)
+ {
+ isSleeping = true;
+ }
+ for (int b = 0; b < bod->getNumLinks(); b++)
+ {
+ if (bod->getLink(b).m_collider && bod->getLink(b).m_collider->getActivationState() == ISLAND_SLEEPING)
+ isSleeping = true;
+ }
+
+ if (!isSleeping)
+ {
+ int nLinks = bod->getNumLinks();
+ bod->predictPositionsMultiDof(timeStep);
+ m_scratch_world_to_local.resize(nLinks + 1);
+ m_scratch_local_origin.resize(nLinks + 1);
+ bod->updateCollisionObjectInterpolationWorldTransforms(m_scratch_world_to_local, m_scratch_local_origin);
+ }
+ else
+ {
+ bod->clearVelocities();
+ }
+ }
}
void btMultiBodyDynamicsWorld::addMultiBodyConstraint(btMultiBodyConstraint* constraint)
@@ -1029,3 +867,8 @@ void btMultiBodyDynamicsWorld::serializeMultiBodies(btSerializer* serializer)
}
}
}
+//
+//void btMultiBodyDynamicsWorld::setSplitIslands(bool split)
+//{
+// m_islandManager->setSplitIslands(split);
+//}
diff --git a/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyDynamicsWorld.h b/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyDynamicsWorld.h
index e36c2f7aad..9ac46f4b64 100644
--- a/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyDynamicsWorld.h
+++ b/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyDynamicsWorld.h
@@ -17,6 +17,7 @@ subject to the following restrictions:
#define BT_MULTIBODY_DYNAMICS_WORLD_H
#include "BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h"
+#include "BulletDynamics/Featherstone/btMultiBodyInplaceSolverIslandCallback.h"
#define BT_USE_VIRTUAL_CLEARFORCES_AND_GRAVITY
@@ -47,7 +48,7 @@ protected:
virtual void calculateSimulationIslands();
virtual void updateActivationState(btScalar timeStep);
- virtual void solveConstraints(btContactSolverInfo& solverInfo);
+
virtual void serializeMultiBodies(btSerializer* serializer);
@@ -55,7 +56,9 @@ public:
btMultiBodyDynamicsWorld(btDispatcher* dispatcher, btBroadphaseInterface* pairCache, btMultiBodyConstraintSolver* constraintSolver, btCollisionConfiguration* collisionConfiguration);
virtual ~btMultiBodyDynamicsWorld();
-
+
+ virtual void solveConstraints(btContactSolverInfo& solverInfo);
+
virtual void addMultiBody(btMultiBody* body, int group = btBroadphaseProxy::DefaultFilter, int mask = btBroadphaseProxy::AllFilter);
virtual void removeMultiBody(btMultiBody* body);
@@ -95,7 +98,10 @@ public:
virtual void removeMultiBodyConstraint(btMultiBodyConstraint* constraint);
virtual void integrateTransforms(btScalar timeStep);
-
+ void integrateMultiBodyTransforms(btScalar timeStep);
+ void predictMultiBodyTransforms(btScalar timeStep);
+
+ virtual void predictUnconstraintMotion(btScalar timeStep);
virtual void debugDrawWorld();
virtual void debugDrawMultiBodyConstraint(btMultiBodyConstraint* constraint);
@@ -110,6 +116,9 @@ public:
virtual void setMultiBodyConstraintSolver(btMultiBodyConstraintSolver* solver);
virtual void setConstraintSolver(btConstraintSolver* solver);
virtual void getAnalyticsData(btAlignedObjectArray<struct btSolverAnalyticsData>& m_islandAnalyticsData) const;
-
+
+ virtual void solveExternalForces(btContactSolverInfo& solverInfo);
+ virtual void solveInternalConstraints(btContactSolverInfo& solverInfo);
+ void buildIslands();
};
#endif //BT_MULTIBODY_DYNAMICS_WORLD_H
diff --git a/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyInplaceSolverIslandCallback.h b/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyInplaceSolverIslandCallback.h
new file mode 100644
index 0000000000..3169b86e61
--- /dev/null
+++ b/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyInplaceSolverIslandCallback.h
@@ -0,0 +1,247 @@
+/*
+ Bullet Continuous Collision Detection and Physics Library
+ Copyright (c) 2019 Google Inc. http://bulletphysics.org
+ 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.
+ */
+
+#ifndef BT_MULTIBODY_INPLACE_SOLVER_ISLAND_CALLBACK_H
+#define BT_MULTIBODY_INPLACE_SOLVER_ISLAND_CALLBACK_H
+
+#include "BulletDynamics/Featherstone/btMultiBodyConstraintSolver.h"
+#include "BulletCollision/CollisionDispatch/btSimulationIslandManager.h"
+#include "BulletDynamics/Featherstone/btMultiBodyDynamicsWorld.h"
+#include "btMultiBodyConstraintSolver.h"
+
+SIMD_FORCE_INLINE int btGetConstraintIslandId2(const btTypedConstraint* lhs)
+{
+ int islandId;
+
+ const btCollisionObject& rcolObj0 = lhs->getRigidBodyA();
+ const btCollisionObject& rcolObj1 = lhs->getRigidBodyB();
+ islandId = rcolObj0.getIslandTag() >= 0 ? rcolObj0.getIslandTag() : rcolObj1.getIslandTag();
+ return islandId;
+}
+class btSortConstraintOnIslandPredicate2
+{
+public:
+ bool operator()(const btTypedConstraint* lhs, const btTypedConstraint* rhs) const
+ {
+ int rIslandId0, lIslandId0;
+ rIslandId0 = btGetConstraintIslandId2(rhs);
+ lIslandId0 = btGetConstraintIslandId2(lhs);
+ return lIslandId0 < rIslandId0;
+ }
+};
+
+SIMD_FORCE_INLINE int btGetMultiBodyConstraintIslandId(const btMultiBodyConstraint* lhs)
+{
+ int islandId;
+
+ int islandTagA = lhs->getIslandIdA();
+ int islandTagB = lhs->getIslandIdB();
+ islandId = islandTagA >= 0 ? islandTagA : islandTagB;
+ return islandId;
+}
+
+class btSortMultiBodyConstraintOnIslandPredicate
+{
+public:
+ bool operator()(const btMultiBodyConstraint* lhs, const btMultiBodyConstraint* rhs) const
+ {
+ int rIslandId0, lIslandId0;
+ rIslandId0 = btGetMultiBodyConstraintIslandId(rhs);
+ lIslandId0 = btGetMultiBodyConstraintIslandId(lhs);
+ return lIslandId0 < rIslandId0;
+ }
+};
+
+struct MultiBodyInplaceSolverIslandCallback : public btSimulationIslandManager::IslandCallback
+{
+
+ btContactSolverInfo* m_solverInfo;
+ btMultiBodyConstraintSolver* m_solver;
+ btMultiBodyConstraint** m_multiBodySortedConstraints;
+ int m_numMultiBodyConstraints;
+
+ btTypedConstraint** m_sortedConstraints;
+ int m_numConstraints;
+ btIDebugDraw* m_debugDrawer;
+ btDispatcher* m_dispatcher;
+
+ btAlignedObjectArray<btCollisionObject*> m_bodies;
+ btAlignedObjectArray<btCollisionObject*> m_softBodies;
+ btAlignedObjectArray<btPersistentManifold*> m_manifolds;
+ btAlignedObjectArray<btTypedConstraint*> m_constraints;
+ btAlignedObjectArray<btMultiBodyConstraint*> m_multiBodyConstraints;
+
+ btAlignedObjectArray<btSolverAnalyticsData> m_islandAnalyticsData;
+
+ MultiBodyInplaceSolverIslandCallback(btMultiBodyConstraintSolver* solver,
+ btDispatcher* dispatcher)
+ : m_solverInfo(NULL),
+ m_solver(solver),
+ m_multiBodySortedConstraints(NULL),
+ m_numConstraints(0),
+ m_debugDrawer(NULL),
+ m_dispatcher(dispatcher)
+ {
+ }
+
+ MultiBodyInplaceSolverIslandCallback& operator=(const MultiBodyInplaceSolverIslandCallback& other)
+ {
+ btAssert(0);
+ (void)other;
+ return *this;
+ }
+
+ SIMD_FORCE_INLINE virtual void setup(btContactSolverInfo* solverInfo, btTypedConstraint** sortedConstraints, int numConstraints, btMultiBodyConstraint** sortedMultiBodyConstraints, int numMultiBodyConstraints, btIDebugDraw* debugDrawer)
+ {
+ m_islandAnalyticsData.clear();
+ btAssert(solverInfo);
+ m_solverInfo = solverInfo;
+
+ m_multiBodySortedConstraints = sortedMultiBodyConstraints;
+ m_numMultiBodyConstraints = numMultiBodyConstraints;
+ m_sortedConstraints = sortedConstraints;
+ m_numConstraints = numConstraints;
+
+ m_debugDrawer = debugDrawer;
+ m_bodies.resize(0);
+ m_manifolds.resize(0);
+ m_constraints.resize(0);
+ m_multiBodyConstraints.resize(0);
+ }
+
+ void setMultiBodyConstraintSolver(btMultiBodyConstraintSolver* solver)
+ {
+ m_solver = solver;
+ }
+
+ virtual void processIsland(btCollisionObject** bodies, int numBodies, btPersistentManifold** manifolds, int numManifolds, int islandId)
+ {
+ if (islandId < 0)
+ {
+ ///we don't split islands, so all constraints/contact manifolds/bodies are passed into the solver regardless the island id
+ m_solver->solveMultiBodyGroup(bodies, numBodies, manifolds, numManifolds, m_sortedConstraints, m_numConstraints, &m_multiBodySortedConstraints[0], m_numConstraints, *m_solverInfo, m_debugDrawer, m_dispatcher);
+ if (m_solverInfo->m_reportSolverAnalytics&1)
+ {
+ m_solver->m_analyticsData.m_islandId = islandId;
+ m_islandAnalyticsData.push_back(m_solver->m_analyticsData);
+ }
+ }
+ else
+ {
+ //also add all non-contact constraints/joints for this island
+ btTypedConstraint** startConstraint = 0;
+ btMultiBodyConstraint** startMultiBodyConstraint = 0;
+
+ int numCurConstraints = 0;
+ int numCurMultiBodyConstraints = 0;
+
+ int i;
+
+ //find the first constraint for this island
+
+ for (i = 0; i < m_numConstraints; i++)
+ {
+ if (btGetConstraintIslandId2(m_sortedConstraints[i]) == islandId)
+ {
+ startConstraint = &m_sortedConstraints[i];
+ break;
+ }
+ }
+ //count the number of constraints in this island
+ for (; i < m_numConstraints; i++)
+ {
+ if (btGetConstraintIslandId2(m_sortedConstraints[i]) == islandId)
+ {
+ numCurConstraints++;
+ }
+ }
+
+ for (i = 0; i < m_numMultiBodyConstraints; i++)
+ {
+ if (btGetMultiBodyConstraintIslandId(m_multiBodySortedConstraints[i]) == islandId)
+ {
+ startMultiBodyConstraint = &m_multiBodySortedConstraints[i];
+ break;
+ }
+ }
+ //count the number of multi body constraints in this island
+ for (; i < m_numMultiBodyConstraints; i++)
+ {
+ if (btGetMultiBodyConstraintIslandId(m_multiBodySortedConstraints[i]) == islandId)
+ {
+ numCurMultiBodyConstraints++;
+ }
+ }
+
+ //if (m_solverInfo->m_minimumSolverBatchSize<=1)
+ //{
+ // m_solver->solveGroup( bodies,numBodies,manifolds, numManifolds,startConstraint,numCurConstraints,*m_solverInfo,m_debugDrawer,m_dispatcher);
+ //} else
+ {
+ for (i = 0; i < numBodies; i++)
+ {
+ bool isSoftBodyType = (bodies[i]->getInternalType() & btCollisionObject::CO_SOFT_BODY);
+ if (!isSoftBodyType)
+ {
+ m_bodies.push_back(bodies[i]);
+ }
+ else
+ {
+ m_softBodies.push_back(bodies[i]);
+ }
+ }
+ for (i = 0; i < numManifolds; i++)
+ m_manifolds.push_back(manifolds[i]);
+ for (i = 0; i < numCurConstraints; i++)
+ m_constraints.push_back(startConstraint[i]);
+
+ for (i = 0; i < numCurMultiBodyConstraints; i++)
+ m_multiBodyConstraints.push_back(startMultiBodyConstraint[i]);
+
+ if ((m_multiBodyConstraints.size() + m_constraints.size() + m_manifolds.size()) > m_solverInfo->m_minimumSolverBatchSize)
+ {
+ processConstraints(islandId);
+ }
+ else
+ {
+ //printf("deferred\n");
+ }
+ }
+ }
+ }
+
+ virtual void processConstraints(int islandId=-1)
+ {
+ btCollisionObject** bodies = m_bodies.size() ? &m_bodies[0] : 0;
+ btPersistentManifold** manifold = m_manifolds.size() ? &m_manifolds[0] : 0;
+ btTypedConstraint** constraints = m_constraints.size() ? &m_constraints[0] : 0;
+ btMultiBodyConstraint** multiBodyConstraints = m_multiBodyConstraints.size() ? &m_multiBodyConstraints[0] : 0;
+
+ //printf("mb contacts = %d, mb constraints = %d\n", mbContacts, m_multiBodyConstraints.size());
+
+ m_solver->solveMultiBodyGroup(bodies, m_bodies.size(), manifold, m_manifolds.size(), constraints, m_constraints.size(), multiBodyConstraints, m_multiBodyConstraints.size(), *m_solverInfo, m_debugDrawer, m_dispatcher);
+ if (m_bodies.size() && (m_solverInfo->m_reportSolverAnalytics&1))
+ {
+ m_solver->m_analyticsData.m_islandId = islandId;
+ m_islandAnalyticsData.push_back(m_solver->m_analyticsData);
+ }
+ m_bodies.resize(0);
+ m_softBodies.resize(0);
+ m_manifolds.resize(0);
+ m_constraints.resize(0);
+ m_multiBodyConstraints.resize(0);
+ }
+};
+
+
+#endif /*BT_MULTIBODY_INPLACE_SOLVER_ISLAND_CALLBACK_H */
diff --git a/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyLink.h b/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyLink.h
index 92d41dfac2..01d5583c2f 100644
--- a/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyLink.h
+++ b/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyLink.h
@@ -111,6 +111,10 @@ struct btMultibodyLink
btQuaternion m_cachedRotParentToThis; // rotates vectors in parent frame to vectors in local frame
btVector3 m_cachedRVector; // vector from COM of parent to COM of this link, in local frame.
+
+ // predicted verstion
+ btQuaternion m_cachedRotParentToThis_interpolate; // rotates vectors in parent frame to vectors in local frame
+ btVector3 m_cachedRVector_interpolate; // vector from COM of parent to COM of this link, in local frame.
btVector3 m_appliedForce; // In WORLD frame
btVector3 m_appliedTorque; // In WORLD frame
@@ -119,6 +123,7 @@ struct btMultibodyLink
btVector3 m_appliedConstraintTorque; // In WORLD frame
btScalar m_jointPos[7];
+ btScalar m_jointPos_interpolate[7];
//m_jointTorque is the joint torque applied by the user using 'addJointTorque'.
//It gets set to zero after each internal stepSimulation call
@@ -152,6 +157,7 @@ struct btMultibodyLink
m_parent(-1),
m_zeroRotParentToThis(0, 0, 0, 1),
m_cachedRotParentToThis(0, 0, 0, 1),
+ m_cachedRotParentToThis_interpolate(0, 0, 0, 1),
m_collider(0),
m_flags(0),
m_dofCount(0),
@@ -174,6 +180,7 @@ struct btMultibodyLink
m_dVector.setValue(0, 0, 0);
m_eVector.setValue(0, 0, 0);
m_cachedRVector.setValue(0, 0, 0);
+ m_cachedRVector_interpolate.setValue(0, 0, 0);
m_appliedForce.setValue(0, 0, 0);
m_appliedTorque.setValue(0, 0, 0);
m_appliedConstraintForce.setValue(0, 0, 0);
@@ -188,42 +195,43 @@ struct btMultibodyLink
// routine to update m_cachedRotParentToThis and m_cachedRVector
void updateCacheMultiDof(btScalar *pq = 0)
{
- btScalar *pJointPos = (pq ? pq : &m_jointPos[0]);
-
+ btScalar *pJointPos = (pq ? pq : &m_jointPos[0]);
+ btQuaternion& cachedRot = m_cachedRotParentToThis;
+ btVector3& cachedVector = m_cachedRVector;
switch (m_jointType)
{
case eRevolute:
{
- m_cachedRotParentToThis = btQuaternion(getAxisTop(0), -pJointPos[0]) * m_zeroRotParentToThis;
- m_cachedRVector = m_dVector + quatRotate(m_cachedRotParentToThis, m_eVector);
+ cachedRot = btQuaternion(getAxisTop(0), -pJointPos[0]) * m_zeroRotParentToThis;
+ cachedVector = m_dVector + quatRotate(m_cachedRotParentToThis, m_eVector);
break;
}
case ePrismatic:
{
// m_cachedRotParentToThis never changes, so no need to update
- m_cachedRVector = m_dVector + quatRotate(m_cachedRotParentToThis, m_eVector) + pJointPos[0] * getAxisBottom(0);
+ cachedVector = m_dVector + quatRotate(m_cachedRotParentToThis, m_eVector) + pJointPos[0] * getAxisBottom(0);
break;
}
case eSpherical:
{
- m_cachedRotParentToThis = btQuaternion(pJointPos[0], pJointPos[1], pJointPos[2], -pJointPos[3]) * m_zeroRotParentToThis;
- m_cachedRVector = m_dVector + quatRotate(m_cachedRotParentToThis, m_eVector);
+ cachedRot = btQuaternion(pJointPos[0], pJointPos[1], pJointPos[2], -pJointPos[3]) * m_zeroRotParentToThis;
+ cachedVector = m_dVector + quatRotate(cachedRot, m_eVector);
break;
}
case ePlanar:
{
- m_cachedRotParentToThis = btQuaternion(getAxisTop(0), -pJointPos[0]) * m_zeroRotParentToThis;
- m_cachedRVector = quatRotate(btQuaternion(getAxisTop(0), -pJointPos[0]), pJointPos[1] * getAxisBottom(1) + pJointPos[2] * getAxisBottom(2)) + quatRotate(m_cachedRotParentToThis, m_eVector);
+ cachedRot = btQuaternion(getAxisTop(0), -pJointPos[0]) * m_zeroRotParentToThis;
+ cachedVector = quatRotate(btQuaternion(getAxisTop(0), -pJointPos[0]), pJointPos[1] * getAxisBottom(1) + pJointPos[2] * getAxisBottom(2)) + quatRotate(cachedRot, m_eVector);
break;
}
case eFixed:
{
- m_cachedRotParentToThis = m_zeroRotParentToThis;
- m_cachedRVector = m_dVector + quatRotate(m_cachedRotParentToThis, m_eVector);
+ cachedRot = m_zeroRotParentToThis;
+ cachedVector = m_dVector + quatRotate(cachedRot, m_eVector);
break;
}
@@ -233,7 +241,60 @@ struct btMultibodyLink
btAssert(0);
}
}
+ m_cachedRotParentToThis_interpolate = m_cachedRotParentToThis;
+ m_cachedRVector_interpolate = m_cachedRVector;
}
+
+ void updateInterpolationCacheMultiDof()
+ {
+ btScalar *pJointPos = &m_jointPos_interpolate[0];
+
+ btQuaternion& cachedRot = m_cachedRotParentToThis_interpolate;
+ btVector3& cachedVector = m_cachedRVector_interpolate;
+ switch (m_jointType)
+ {
+ case eRevolute:
+ {
+ cachedRot = btQuaternion(getAxisTop(0), -pJointPos[0]) * m_zeroRotParentToThis;
+ cachedVector = m_dVector + quatRotate(m_cachedRotParentToThis, m_eVector);
+
+ break;
+ }
+ case ePrismatic:
+ {
+ // m_cachedRotParentToThis never changes, so no need to update
+ cachedVector = m_dVector + quatRotate(m_cachedRotParentToThis, m_eVector) + pJointPos[0] * getAxisBottom(0);
+
+ break;
+ }
+ case eSpherical:
+ {
+ cachedRot = btQuaternion(pJointPos[0], pJointPos[1], pJointPos[2], -pJointPos[3]) * m_zeroRotParentToThis;
+ cachedVector = m_dVector + quatRotate(cachedRot, m_eVector);
+
+ break;
+ }
+ case ePlanar:
+ {
+ cachedRot = btQuaternion(getAxisTop(0), -pJointPos[0]) * m_zeroRotParentToThis;
+ cachedVector = quatRotate(btQuaternion(getAxisTop(0), -pJointPos[0]), pJointPos[1] * getAxisBottom(1) + pJointPos[2] * getAxisBottom(2)) + quatRotate(cachedRot, m_eVector);
+
+ break;
+ }
+ case eFixed:
+ {
+ cachedRot = m_zeroRotParentToThis;
+ cachedVector = m_dVector + quatRotate(cachedRot, m_eVector);
+
+ break;
+ }
+ default:
+ {
+ //invalid type
+ btAssert(0);
+ }
+ }
+ }
};
#endif //BT_MULTIBODY_LINK_H
diff --git a/thirdparty/bullet/BulletDynamics/MLCPSolvers/btLemkeSolver.h b/thirdparty/bullet/BulletDynamics/MLCPSolvers/btLemkeSolver.h
index ac2fc46ab0..f18c4ea41b 100644
--- a/thirdparty/bullet/BulletDynamics/MLCPSolvers/btLemkeSolver.h
+++ b/thirdparty/bullet/BulletDynamics/MLCPSolvers/btLemkeSolver.h
@@ -20,7 +20,7 @@ subject to the following restrictions:
#include "btMLCPSolverInterface.h"
#include "btLemkeAlgorithm.h"
-///The btLemkeSolver is based on "Fast Implementation of Lemke's Algorithm for Rigid Body Contact Simulation (John E. Lloyd) "
+///The btLemkeSolver is based on "Fast Implementation of Lemke’s Algorithm for Rigid Body Contact Simulation (John E. Lloyd) "
///It is a slower but more accurate solver. Increase the m_maxLoops for better convergence, at the cost of more CPU time.
///The original implementation of the btLemkeAlgorithm was done by Kilian Grundl from the MBSim team
class btLemkeSolver : public btMLCPSolverInterface
diff --git a/thirdparty/bullet/BulletSoftBody/DeformableBodyInplaceSolverIslandCallback.h b/thirdparty/bullet/BulletSoftBody/DeformableBodyInplaceSolverIslandCallback.h
new file mode 100644
index 0000000000..7b225701f6
--- /dev/null
+++ b/thirdparty/bullet/BulletSoftBody/DeformableBodyInplaceSolverIslandCallback.h
@@ -0,0 +1,46 @@
+//
+// DeformableBodyInplaceSolverIslandCallback.h
+// BulletSoftBody
+//
+// Created by Xuchen Han on 12/16/19.
+//
+
+#ifndef DeformableBodyInplaceSolverIslandCallback_h
+#define DeformableBodyInplaceSolverIslandCallback_h
+
+struct DeformableBodyInplaceSolverIslandCallback : public MultiBodyInplaceSolverIslandCallback
+{
+ btDeformableMultiBodyConstraintSolver* m_deformableSolver;
+
+ DeformableBodyInplaceSolverIslandCallback(btDeformableMultiBodyConstraintSolver* solver,
+ btDispatcher* dispatcher)
+ : MultiBodyInplaceSolverIslandCallback(solver, dispatcher), m_deformableSolver(solver)
+ {
+ }
+
+
+ virtual void processConstraints(int islandId=-1)
+ {
+ btCollisionObject** bodies = m_bodies.size() ? &m_bodies[0] : 0;
+ btCollisionObject** softBodies = m_softBodies.size() ? &m_softBodies[0] : 0;
+ btPersistentManifold** manifold = m_manifolds.size() ? &m_manifolds[0] : 0;
+ btTypedConstraint** constraints = m_constraints.size() ? &m_constraints[0] : 0;
+ btMultiBodyConstraint** multiBodyConstraints = m_multiBodyConstraints.size() ? &m_multiBodyConstraints[0] : 0;
+
+ //printf("mb contacts = %d, mb constraints = %d\n", mbContacts, m_multiBodyConstraints.size());
+
+ m_deformableSolver->solveDeformableBodyGroup(bodies, m_bodies.size(), softBodies, m_softBodies.size(), manifold, m_manifolds.size(), constraints, m_constraints.size(), multiBodyConstraints, m_multiBodyConstraints.size(), *m_solverInfo, m_debugDrawer, m_dispatcher);
+ if (m_bodies.size() && (m_solverInfo->m_reportSolverAnalytics&1))
+ {
+ m_deformableSolver->m_analyticsData.m_islandId = islandId;
+ m_islandAnalyticsData.push_back(m_solver->m_analyticsData);
+ }
+ m_bodies.resize(0);
+ m_softBodies.resize(0);
+ m_manifolds.resize(0);
+ m_constraints.resize(0);
+ m_multiBodyConstraints.resize(0);
+ }
+};
+
+#endif /* DeformableBodyInplaceSolverIslandCallback_h */
diff --git a/thirdparty/bullet/BulletSoftBody/btCGProjection.h b/thirdparty/bullet/BulletSoftBody/btCGProjection.h
new file mode 100644
index 0000000000..d047e6d3d9
--- /dev/null
+++ b/thirdparty/bullet/BulletSoftBody/btCGProjection.h
@@ -0,0 +1,106 @@
+/*
+ Written by Xuchen Han <xuchenhan2015@u.northwestern.edu>
+
+ Bullet Continuous Collision Detection and Physics Library
+ Copyright (c) 2019 Google Inc. http://bulletphysics.org
+ 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.
+ */
+
+#ifndef BT_CG_PROJECTION_H
+#define BT_CG_PROJECTION_H
+
+#include "btSoftBody.h"
+#include "BulletDynamics/Featherstone/btMultiBodyLinkCollider.h"
+#include "BulletDynamics/Featherstone/btMultiBodyConstraint.h"
+
+struct DeformableContactConstraint
+{
+ const btSoftBody::Node* m_node;
+ btAlignedObjectArray<const btSoftBody::RContact*> m_contact;
+ btAlignedObjectArray<btVector3> m_total_normal_dv;
+ btAlignedObjectArray<btVector3> m_total_tangent_dv;
+ btAlignedObjectArray<bool> m_static;
+ btAlignedObjectArray<bool> m_can_be_dynamic;
+
+ DeformableContactConstraint(const btSoftBody::RContact& rcontact): m_node(rcontact.m_node)
+ {
+ append(rcontact);
+ }
+
+ DeformableContactConstraint(): m_node(NULL)
+ {
+ m_contact.push_back(NULL);
+ }
+
+ void append(const btSoftBody::RContact& rcontact)
+ {
+ m_contact.push_back(&rcontact);
+ m_total_normal_dv.push_back(btVector3(0,0,0));
+ m_total_tangent_dv.push_back(btVector3(0,0,0));
+ m_static.push_back(false);
+ m_can_be_dynamic.push_back(true);
+ }
+
+ void replace(const btSoftBody::RContact& rcontact)
+ {
+ m_contact.clear();
+ m_total_normal_dv.clear();
+ m_total_tangent_dv.clear();
+ m_static.clear();
+ m_can_be_dynamic.clear();
+ append(rcontact);
+ }
+
+ ~DeformableContactConstraint()
+ {
+ }
+};
+
+class btCGProjection
+{
+public:
+ typedef btAlignedObjectArray<btVector3> TVStack;
+ typedef btAlignedObjectArray<btAlignedObjectArray<btVector3> > TVArrayStack;
+ typedef btAlignedObjectArray<btAlignedObjectArray<btScalar> > TArrayStack;
+ btAlignedObjectArray<btSoftBody *>& m_softBodies;
+ const btScalar& m_dt;
+ // map from node indices to node pointers
+ const btAlignedObjectArray<btSoftBody::Node*>* m_nodes;
+
+ btCGProjection(btAlignedObjectArray<btSoftBody *>& softBodies, const btScalar& dt)
+ : m_softBodies(softBodies)
+ , m_dt(dt)
+ {
+ }
+
+ virtual ~btCGProjection()
+ {
+ }
+
+ // apply the constraints
+ virtual void project(TVStack& x) = 0;
+
+ virtual void setConstraints() = 0;
+
+ // update the constraints
+ virtual btScalar update() = 0;
+
+ virtual void reinitialize(bool nodeUpdated)
+ {
+ }
+
+ virtual void setIndices(const btAlignedObjectArray<btSoftBody::Node*>* nodes)
+ {
+ m_nodes = nodes;
+ }
+};
+
+
+#endif /* btCGProjection_h */
diff --git a/thirdparty/bullet/BulletSoftBody/btConjugateGradient.h b/thirdparty/bullet/BulletSoftBody/btConjugateGradient.h
new file mode 100644
index 0000000000..bd51e584b9
--- /dev/null
+++ b/thirdparty/bullet/BulletSoftBody/btConjugateGradient.h
@@ -0,0 +1,158 @@
+/*
+ Written by Xuchen Han <xuchenhan2015@u.northwestern.edu>
+
+ Bullet Continuous Collision Detection and Physics Library
+ Copyright (c) 2019 Google Inc. http://bulletphysics.org
+ 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.
+ */
+
+#ifndef BT_CONJUGATE_GRADIENT_H
+#define BT_CONJUGATE_GRADIENT_H
+#include <iostream>
+#include <cmath>
+#include <limits>
+#include <LinearMath/btAlignedObjectArray.h>
+#include <LinearMath/btVector3.h>
+#include "LinearMath/btQuickprof.h"
+template <class MatrixX>
+class btConjugateGradient
+{
+ typedef btAlignedObjectArray<btVector3> TVStack;
+ TVStack r,p,z,temp;
+ int max_iterations;
+ btScalar tolerance_squared;
+public:
+ btConjugateGradient(const int max_it_in)
+ : max_iterations(max_it_in)
+ {
+ tolerance_squared = 1e-5;
+ }
+
+ virtual ~btConjugateGradient(){}
+
+ // return the number of iterations taken
+ int solve(MatrixX& A, TVStack& x, const TVStack& b, bool verbose = false)
+ {
+ BT_PROFILE("CGSolve");
+ btAssert(x.size() == b.size());
+ reinitialize(b);
+ // r = b - A * x --with assigned dof zeroed out
+ A.multiply(x, temp);
+ r = sub(b, temp);
+ A.project(r);
+ // z = M^(-1) * r
+ A.precondition(r, z);
+ A.project(z);
+ btScalar r_dot_z = dot(z,r);
+ if (r_dot_z <= tolerance_squared) {
+ if (verbose)
+ {
+ std::cout << "Iteration = 0" << std::endl;
+ std::cout << "Two norm of the residual = " << r_dot_z << std::endl;
+ }
+ return 0;
+ }
+ p = z;
+ btScalar r_dot_z_new = r_dot_z;
+ for (int k = 1; k <= max_iterations; k++) {
+ // temp = A*p
+ A.multiply(p, temp);
+ A.project(temp);
+ if (dot(p,temp) < SIMD_EPSILON)
+ {
+ if (verbose)
+ std::cout << "Encountered negative direction in CG!" << std::endl;
+ if (k == 1)
+ {
+ x = b;
+ }
+ return k;
+ }
+ // alpha = r^T * z / (p^T * A * p)
+ btScalar alpha = r_dot_z_new / dot(p, temp);
+ // x += alpha * p;
+ multAndAddTo(alpha, p, x);
+ // r -= alpha * temp;
+ multAndAddTo(-alpha, temp, r);
+ // z = M^(-1) * r
+ A.precondition(r, z);
+ r_dot_z = r_dot_z_new;
+ r_dot_z_new = dot(r,z);
+ if (r_dot_z_new < tolerance_squared) {
+ if (verbose)
+ {
+ std::cout << "ConjugateGradient iterations " << k << std::endl;
+ }
+ return k;
+ }
+
+ btScalar beta = r_dot_z_new/r_dot_z;
+ p = multAndAdd(beta, p, z);
+ }
+ if (verbose)
+ {
+ std::cout << "ConjugateGradient max iterations reached " << max_iterations << std::endl;
+ }
+ return max_iterations;
+ }
+
+ void reinitialize(const TVStack& b)
+ {
+ r.resize(b.size());
+ p.resize(b.size());
+ z.resize(b.size());
+ temp.resize(b.size());
+ }
+
+ TVStack sub(const TVStack& a, const TVStack& b)
+ {
+ // c = a-b
+ btAssert(a.size() == b.size());
+ TVStack c;
+ c.resize(a.size());
+ for (int i = 0; i < a.size(); ++i)
+ {
+ c[i] = a[i] - b[i];
+ }
+ return c;
+ }
+
+ btScalar squaredNorm(const TVStack& a)
+ {
+ return dot(a,a);
+ }
+
+ btScalar dot(const TVStack& a, const TVStack& b)
+ {
+ btScalar ans(0);
+ for (int i = 0; i < a.size(); ++i)
+ ans += a[i].dot(b[i]);
+ return ans;
+ }
+
+ void multAndAddTo(btScalar s, const TVStack& a, TVStack& result)
+ {
+// result += s*a
+ btAssert(a.size() == result.size());
+ for (int i = 0; i < a.size(); ++i)
+ result[i] += s * a[i];
+ }
+
+ TVStack multAndAdd(btScalar s, const TVStack& a, const TVStack& b)
+ {
+ // result = a*s + b
+ TVStack result;
+ result.resize(a.size());
+ for (int i = 0; i < a.size(); ++i)
+ result[i] = s * a[i] + b[i];
+ return result;
+ }
+};
+#endif /* btConjugateGradient_h */
diff --git a/thirdparty/bullet/BulletSoftBody/btDefaultSoftBodySolver.cpp b/thirdparty/bullet/BulletSoftBody/btDefaultSoftBodySolver.cpp
index 8b7ff9abcd..5a79ef86e2 100644
--- a/thirdparty/bullet/BulletSoftBody/btDefaultSoftBodySolver.cpp
+++ b/thirdparty/bullet/BulletSoftBody/btDefaultSoftBodySolver.cpp
@@ -60,7 +60,7 @@ bool btDefaultSoftBodySolver::checkInitialized()
return true;
}
-void btDefaultSoftBodySolver::solveConstraints(float solverdt)
+void btDefaultSoftBodySolver::solveConstraints(btScalar solverdt)
{
// Solve constraints for non-solver softbodies
for (int i = 0; i < m_softBodySet.size(); ++i)
@@ -132,7 +132,7 @@ void btDefaultSoftBodySolver::processCollision(btSoftBody *softBody, const btCol
softBody->defaultCollisionHandler(collisionObjectWrap);
} // btDefaultSoftBodySolver::processCollision
-void btDefaultSoftBodySolver::predictMotion(float timeStep)
+void btDefaultSoftBodySolver::predictMotion(btScalar timeStep)
{
for (int i = 0; i < m_softBodySet.size(); ++i)
{
diff --git a/thirdparty/bullet/BulletSoftBody/btDefaultSoftBodySolver.h b/thirdparty/bullet/BulletSoftBody/btDefaultSoftBodySolver.h
index 50bd735165..3965b07c58 100644
--- a/thirdparty/bullet/BulletSoftBody/btDefaultSoftBodySolver.h
+++ b/thirdparty/bullet/BulletSoftBody/btDefaultSoftBodySolver.h
@@ -46,9 +46,9 @@ public:
virtual void copyBackToSoftBodies(bool bMove = true);
- virtual void solveConstraints(float solverdt);
+ virtual void solveConstraints(btScalar solverdt);
- virtual void predictMotion(float solverdt);
+ virtual void predictMotion(btScalar solverdt);
virtual void copySoftBodyToVertexBuffer(const btSoftBody *const softBody, btVertexBufferDescriptor *vertexBuffer);
diff --git a/thirdparty/bullet/BulletSoftBody/btDeformableBackwardEulerObjective.cpp b/thirdparty/bullet/BulletSoftBody/btDeformableBackwardEulerObjective.cpp
new file mode 100644
index 0000000000..1b247641aa
--- /dev/null
+++ b/thirdparty/bullet/BulletSoftBody/btDeformableBackwardEulerObjective.cpp
@@ -0,0 +1,197 @@
+/*
+ Written by Xuchen Han <xuchenhan2015@u.northwestern.edu>
+
+ Bullet Continuous Collision Detection and Physics Library
+ Copyright (c) 2019 Google Inc. http://bulletphysics.org
+ 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.
+ */
+
+#include "btDeformableBackwardEulerObjective.h"
+#include "btPreconditioner.h"
+#include "LinearMath/btQuickprof.h"
+
+btDeformableBackwardEulerObjective::btDeformableBackwardEulerObjective(btAlignedObjectArray<btSoftBody *>& softBodies, const TVStack& backup_v)
+: m_softBodies(softBodies)
+, m_projection(softBodies)
+, m_backupVelocity(backup_v)
+, m_implicit(false)
+{
+ m_preconditioner = new MassPreconditioner(m_softBodies);
+}
+
+btDeformableBackwardEulerObjective::~btDeformableBackwardEulerObjective()
+{
+ delete m_preconditioner;
+}
+
+void btDeformableBackwardEulerObjective::reinitialize(bool nodeUpdated, btScalar dt)
+{
+ BT_PROFILE("reinitialize");
+ if (dt > 0)
+ {
+ setDt(dt);
+ }
+ if(nodeUpdated)
+ {
+ updateId();
+ }
+ for (int i = 0; i < m_lf.size(); ++i)
+ {
+ m_lf[i]->reinitialize(nodeUpdated);
+ }
+ m_projection.reinitialize(nodeUpdated);
+ m_preconditioner->reinitialize(nodeUpdated);
+}
+
+void btDeformableBackwardEulerObjective::setDt(btScalar dt)
+{
+ m_dt = dt;
+}
+
+void btDeformableBackwardEulerObjective::multiply(const TVStack& x, TVStack& b) const
+{
+ BT_PROFILE("multiply");
+ // add in the mass term
+ size_t counter = 0;
+ for (int i = 0; i < m_softBodies.size(); ++i)
+ {
+ btSoftBody* psb = m_softBodies[i];
+ for (int j = 0; j < psb->m_nodes.size(); ++j)
+ {
+ const btSoftBody::Node& node = psb->m_nodes[j];
+ b[counter] = (node.m_im == 0) ? btVector3(0,0,0) : x[counter] / node.m_im;
+ ++counter;
+ }
+ }
+
+ for (int i = 0; i < m_lf.size(); ++i)
+ {
+ // add damping matrix
+ m_lf[i]->addScaledDampingForceDifferential(-m_dt, x, b);
+ if (m_implicit)
+ {
+ m_lf[i]->addScaledElasticForceDifferential(-m_dt*m_dt, x, b);
+ }
+ }
+}
+
+void btDeformableBackwardEulerObjective::updateVelocity(const TVStack& dv)
+{
+ for (int i = 0; i < m_softBodies.size(); ++i)
+ {
+ btSoftBody* psb = m_softBodies[i];
+ for (int j = 0; j < psb->m_nodes.size(); ++j)
+ {
+ btSoftBody::Node& node = psb->m_nodes[j];
+ node.m_v = m_backupVelocity[node.index] + dv[node.index];
+ }
+ }
+}
+
+void btDeformableBackwardEulerObjective::applyForce(TVStack& force, bool setZero)
+{
+ size_t counter = 0;
+ for (int i = 0; i < m_softBodies.size(); ++i)
+ {
+ btSoftBody* psb = m_softBodies[i];
+ if (!psb->isActive())
+ {
+ counter += psb->m_nodes.size();
+ continue;
+ }
+ for (int j = 0; j < psb->m_nodes.size(); ++j)
+ {
+ btScalar one_over_mass = (psb->m_nodes[j].m_im == 0) ? 0 : psb->m_nodes[j].m_im;
+ psb->m_nodes[j].m_v += one_over_mass * force[counter++];
+ }
+ }
+ if (setZero)
+ {
+ for (int i = 0; i < force.size(); ++i)
+ force[i].setZero();
+ }
+}
+
+void btDeformableBackwardEulerObjective::computeResidual(btScalar dt, TVStack &residual)
+{
+ BT_PROFILE("computeResidual");
+ // add implicit force
+ for (int i = 0; i < m_lf.size(); ++i)
+ {
+ if (m_implicit)
+ {
+ m_lf[i]->addScaledForces(dt, residual);
+ }
+ else
+ {
+ m_lf[i]->addScaledDampingForce(dt, residual);
+ }
+ }
+ m_projection.project(residual);
+}
+
+btScalar btDeformableBackwardEulerObjective::computeNorm(const TVStack& residual) const
+{
+ btScalar mag = 0;
+ for (int i = 0; i < residual.size(); ++i)
+ {
+ mag += residual[i].length2();
+ }
+ return std::sqrt(mag);
+}
+
+btScalar btDeformableBackwardEulerObjective::totalEnergy(btScalar dt)
+{
+ btScalar e = 0;
+ for (int i = 0; i < m_lf.size(); ++i)
+ {
+ e += m_lf[i]->totalEnergy(dt);
+ }
+ return e;
+}
+
+void btDeformableBackwardEulerObjective::applyExplicitForce(TVStack& force)
+{
+ for (int i = 0; i < m_softBodies.size(); ++i)
+ {
+ m_softBodies[i]->advanceDeformation();
+ }
+
+ for (int i = 0; i < m_lf.size(); ++i)
+ {
+ m_lf[i]->addScaledExplicitForce(m_dt, force);
+ }
+ applyForce(force, true);
+}
+
+void btDeformableBackwardEulerObjective::initialGuess(TVStack& dv, const TVStack& residual)
+{
+ size_t counter = 0;
+ for (int i = 0; i < m_softBodies.size(); ++i)
+ {
+ btSoftBody* psb = m_softBodies[i];
+ for (int j = 0; j < psb->m_nodes.size(); ++j)
+ {
+ dv[counter] = psb->m_nodes[j].m_im * residual[counter];
+ ++counter;
+ }
+ }
+}
+
+//set constraints as projections
+void btDeformableBackwardEulerObjective::setConstraints()
+{
+ m_projection.setConstraints();
+}
+
+void btDeformableBackwardEulerObjective::applyDynamicFriction(TVStack& r)
+{
+ m_projection.applyDynamicFriction(r);
+}
diff --git a/thirdparty/bullet/BulletSoftBody/btDeformableBackwardEulerObjective.h b/thirdparty/bullet/BulletSoftBody/btDeformableBackwardEulerObjective.h
new file mode 100644
index 0000000000..05ab42ff0a
--- /dev/null
+++ b/thirdparty/bullet/BulletSoftBody/btDeformableBackwardEulerObjective.h
@@ -0,0 +1,134 @@
+/*
+ Written by Xuchen Han <xuchenhan2015@u.northwestern.edu>
+
+ Bullet Continuous Collision Detection and Physics Library
+ Copyright (c) 2019 Google Inc. http://bulletphysics.org
+ 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.
+ */
+
+#ifndef BT_BACKWARD_EULER_OBJECTIVE_H
+#define BT_BACKWARD_EULER_OBJECTIVE_H
+#include "btConjugateGradient.h"
+#include "btDeformableLagrangianForce.h"
+#include "btDeformableMassSpringForce.h"
+#include "btDeformableGravityForce.h"
+#include "btDeformableCorotatedForce.h"
+#include "btDeformableLinearElasticityForce.h"
+#include "btDeformableNeoHookeanForce.h"
+#include "btDeformableContactProjection.h"
+#include "btPreconditioner.h"
+#include "btDeformableMultiBodyDynamicsWorld.h"
+#include "LinearMath/btQuickprof.h"
+
+class btDeformableBackwardEulerObjective
+{
+public:
+ typedef btAlignedObjectArray<btVector3> TVStack;
+ btScalar m_dt;
+ btAlignedObjectArray<btDeformableLagrangianForce*> m_lf;
+ btAlignedObjectArray<btSoftBody *>& m_softBodies;
+ Preconditioner* m_preconditioner;
+ btDeformableContactProjection m_projection;
+ const TVStack& m_backupVelocity;
+ btAlignedObjectArray<btSoftBody::Node* > m_nodes;
+ bool m_implicit;
+
+ btDeformableBackwardEulerObjective(btAlignedObjectArray<btSoftBody *>& softBodies, const TVStack& backup_v);
+
+ virtual ~btDeformableBackwardEulerObjective();
+
+ void initialize(){}
+
+ // compute the rhs for CG solve, i.e, add the dt scaled implicit force to residual
+ void computeResidual(btScalar dt, TVStack& residual);
+
+ // add explicit force to the velocity
+ void applyExplicitForce(TVStack& force);
+
+ // apply force to velocity and optionally reset the force to zero
+ void applyForce(TVStack& force, bool setZero);
+
+ // compute the norm of the residual
+ btScalar computeNorm(const TVStack& residual) const;
+
+ // compute one step of the solve (there is only one solve if the system is linear)
+ void computeStep(TVStack& dv, const TVStack& residual, const btScalar& dt);
+
+ // perform A*x = b
+ void multiply(const TVStack& x, TVStack& b) const;
+
+ // set initial guess for CG solve
+ void initialGuess(TVStack& dv, const TVStack& residual);
+
+ // reset data structure and reset dt
+ void reinitialize(bool nodeUpdated, btScalar dt);
+
+ void setDt(btScalar dt);
+
+ // add friction force to residual
+ void applyDynamicFriction(TVStack& r);
+
+ // add dv to velocity
+ void updateVelocity(const TVStack& dv);
+
+ //set constraints as projections
+ void setConstraints();
+
+ // update the projections and project the residual
+ void project(TVStack& r)
+ {
+ BT_PROFILE("project");
+ m_projection.project(r);
+ }
+
+ // perform precondition M^(-1) x = b
+ void precondition(const TVStack& x, TVStack& b)
+ {
+ m_preconditioner->operator()(x,b);
+ }
+
+ // reindex all the vertices
+ virtual void updateId()
+ {
+ size_t node_id = 0;
+ size_t face_id = 0;
+ m_nodes.clear();
+ for (int i = 0; i < m_softBodies.size(); ++i)
+ {
+ btSoftBody* psb = m_softBodies[i];
+ for (int j = 0; j < psb->m_nodes.size(); ++j)
+ {
+ psb->m_nodes[j].index = node_id;
+ m_nodes.push_back(&psb->m_nodes[j]);
+ ++node_id;
+ }
+ for (int j = 0; j < psb->m_faces.size(); ++j)
+ {
+ psb->m_faces[j].m_index = face_id;
+ ++face_id;
+ }
+ }
+ }
+
+ const btAlignedObjectArray<btSoftBody::Node*>* getIndices() const
+ {
+ return &m_nodes;
+ }
+
+ void setImplicit(bool implicit)
+ {
+ m_implicit = implicit;
+ }
+
+ // Calculate the total potential energy in the system
+ btScalar totalEnergy(btScalar dt);
+};
+
+#endif /* btBackwardEulerObjective_h */
diff --git a/thirdparty/bullet/BulletSoftBody/btDeformableBodySolver.cpp b/thirdparty/bullet/BulletSoftBody/btDeformableBodySolver.cpp
new file mode 100644
index 0000000000..7724a8ec69
--- /dev/null
+++ b/thirdparty/bullet/BulletSoftBody/btDeformableBodySolver.cpp
@@ -0,0 +1,485 @@
+/*
+ Written by Xuchen Han <xuchenhan2015@u.northwestern.edu>
+
+ Bullet Continuous Collision Detection and Physics Library
+ Copyright (c) 2019 Google Inc. http://bulletphysics.org
+ 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.
+ */
+
+#include <stdio.h>
+#include <limits>
+#include "btDeformableBodySolver.h"
+#include "btSoftBodyInternals.h"
+#include "LinearMath/btQuickprof.h"
+static const int kMaxConjugateGradientIterations = 50;
+btDeformableBodySolver::btDeformableBodySolver()
+: m_numNodes(0)
+, m_cg(kMaxConjugateGradientIterations)
+, m_maxNewtonIterations(5)
+, m_newtonTolerance(1e-4)
+, m_lineSearch(false)
+{
+ m_objective = new btDeformableBackwardEulerObjective(m_softBodies, m_backupVelocity);
+}
+
+btDeformableBodySolver::~btDeformableBodySolver()
+{
+ delete m_objective;
+}
+
+void btDeformableBodySolver::solveDeformableConstraints(btScalar solverdt)
+{
+ BT_PROFILE("solveDeformableConstraints");
+ if (!m_implicit)
+ {
+ m_objective->computeResidual(solverdt, m_residual);
+ m_objective->applyDynamicFriction(m_residual);
+ computeStep(m_dv, m_residual);
+ updateVelocity();
+ }
+ else
+ {
+ for (int i = 0; i < m_maxNewtonIterations; ++i)
+ {
+ updateState();
+ // add the inertia term in the residual
+ int counter = 0;
+ for (int k = 0; k < m_softBodies.size(); ++k)
+ {
+ btSoftBody* psb = m_softBodies[k];
+ for (int j = 0; j < psb->m_nodes.size(); ++j)
+ {
+ if (psb->m_nodes[j].m_im > 0)
+ {
+ m_residual[counter] = (-1./psb->m_nodes[j].m_im) * m_dv[counter];
+ }
+ ++counter;
+ }
+ }
+
+ m_objective->computeResidual(solverdt, m_residual);
+ if (m_objective->computeNorm(m_residual) < m_newtonTolerance && i > 0)
+ {
+ break;
+ }
+ // todo xuchenhan@: this really only needs to be calculated once
+ m_objective->applyDynamicFriction(m_residual);
+ if (m_lineSearch)
+ {
+ btScalar inner_product = computeDescentStep(m_ddv,m_residual);
+ btScalar alpha = 0.01, beta = 0.5; // Boyd & Vandenberghe suggested alpha between 0.01 and 0.3, beta between 0.1 to 0.8
+ btScalar scale = 2;
+ btScalar f0 = m_objective->totalEnergy(solverdt)+kineticEnergy(), f1, f2;
+ backupDv();
+ do {
+ scale *= beta;
+ if (scale < 1e-8) {
+ return;
+ }
+ updateEnergy(scale);
+ f1 = m_objective->totalEnergy(solverdt)+kineticEnergy();
+ f2 = f0 - alpha * scale * inner_product;
+ } while (!(f1 < f2+SIMD_EPSILON)); // if anything here is nan then the search continues
+ revertDv();
+ updateDv(scale);
+ }
+ else
+ {
+ computeStep(m_ddv, m_residual);
+ updateDv();
+ }
+ for (int j = 0; j < m_numNodes; ++j)
+ {
+ m_ddv[j].setZero();
+ m_residual[j].setZero();
+ }
+ }
+ updateVelocity();
+ }
+}
+
+btScalar btDeformableBodySolver::kineticEnergy()
+{
+ btScalar ke = 0;
+ for (int i = 0; i < m_softBodies.size();++i)
+ {
+ btSoftBody* psb = m_softBodies[i];
+ for (int j = 0; j < psb->m_nodes.size();++j)
+ {
+ btSoftBody::Node& node = psb->m_nodes[j];
+ if (node.m_im > 0)
+ {
+ ke += m_dv[node.index].length2() * 0.5 / node.m_im;
+ }
+ }
+ }
+ return ke;
+}
+
+void btDeformableBodySolver::backupDv()
+{
+ m_backup_dv.resize(m_dv.size());
+ for (int i = 0; i<m_backup_dv.size(); ++i)
+ {
+ m_backup_dv[i] = m_dv[i];
+ }
+}
+
+void btDeformableBodySolver::revertDv()
+{
+ for (int i = 0; i<m_backup_dv.size(); ++i)
+ {
+ m_dv[i] = m_backup_dv[i];
+ }
+}
+
+void btDeformableBodySolver::updateEnergy(btScalar scale)
+{
+ for (int i = 0; i<m_dv.size(); ++i)
+ {
+ m_dv[i] = m_backup_dv[i] + scale * m_ddv[i];
+ }
+ updateState();
+}
+
+
+btScalar btDeformableBodySolver::computeDescentStep(TVStack& ddv, const TVStack& residual, bool verbose)
+{
+ m_cg.solve(*m_objective, ddv, residual, false);
+ btScalar inner_product = m_cg.dot(residual, m_ddv);
+ btScalar res_norm = m_objective->computeNorm(residual);
+ btScalar tol = 1e-5 * res_norm * m_objective->computeNorm(m_ddv);
+ if (inner_product < -tol)
+ {
+ if (verbose)
+ {
+ std::cout << "Looking backwards!" << std::endl;
+ }
+ for (int i = 0; i < m_ddv.size();++i)
+ {
+ m_ddv[i] = -m_ddv[i];
+ }
+ inner_product = -inner_product;
+ }
+ else if (std::abs(inner_product) < tol)
+ {
+ if (verbose)
+ {
+ std::cout << "Gradient Descent!" << std::endl;
+ }
+ btScalar scale = m_objective->computeNorm(m_ddv) / res_norm;
+ for (int i = 0; i < m_ddv.size();++i)
+ {
+ m_ddv[i] = scale * residual[i];
+ }
+ inner_product = scale * res_norm * res_norm;
+ }
+ return inner_product;
+}
+
+void btDeformableBodySolver::updateState()
+{
+ updateVelocity();
+ updateTempPosition();
+}
+
+void btDeformableBodySolver::updateDv(btScalar scale)
+{
+ for (int i = 0; i < m_numNodes; ++i)
+ {
+ m_dv[i] += scale * m_ddv[i];
+ }
+}
+
+void btDeformableBodySolver::computeStep(TVStack& ddv, const TVStack& residual)
+{
+ m_cg.solve(*m_objective, ddv, residual);
+}
+
+void btDeformableBodySolver::reinitialize(const btAlignedObjectArray<btSoftBody *>& softBodies, btScalar dt)
+{
+ m_softBodies.copyFromArray(softBodies);
+ bool nodeUpdated = updateNodes();
+
+ if (nodeUpdated)
+ {
+ m_dv.resize(m_numNodes, btVector3(0,0,0));
+ m_ddv.resize(m_numNodes, btVector3(0,0,0));
+ m_residual.resize(m_numNodes, btVector3(0,0,0));
+ m_backupVelocity.resize(m_numNodes, btVector3(0,0,0));
+ }
+
+ // need to setZero here as resize only set value for newly allocated items
+ for (int i = 0; i < m_numNodes; ++i)
+ {
+ m_dv[i].setZero();
+ m_ddv[i].setZero();
+ m_residual[i].setZero();
+ }
+
+ m_dt = dt;
+ m_objective->reinitialize(nodeUpdated, dt);
+}
+
+void btDeformableBodySolver::setConstraints()
+{
+ BT_PROFILE("setConstraint");
+ m_objective->setConstraints();
+}
+
+btScalar btDeformableBodySolver::solveContactConstraints(btCollisionObject** deformableBodies,int numDeformableBodies)
+{
+ BT_PROFILE("solveContactConstraints");
+ btScalar maxSquaredResidual = m_objective->m_projection.update(deformableBodies,numDeformableBodies);
+ return maxSquaredResidual;
+}
+
+btScalar btDeformableBodySolver::solveSplitImpulse(const btContactSolverInfo& infoGlobal)
+{
+ BT_PROFILE("solveSplitImpulse");
+ return m_objective->m_projection.solveSplitImpulse(infoGlobal);
+}
+
+void btDeformableBodySolver::splitImpulseSetup(const btContactSolverInfo& infoGlobal)
+{
+ m_objective->m_projection.splitImpulseSetup(infoGlobal);
+}
+
+void btDeformableBodySolver::updateVelocity()
+{
+ int counter = 0;
+ for (int i = 0; i < m_softBodies.size(); ++i)
+ {
+ btSoftBody* psb = m_softBodies[i];
+ psb->m_maxSpeedSquared = 0;
+ if (!psb->isActive())
+ {
+ counter += psb->m_nodes.size();
+ continue;
+ }
+ for (int j = 0; j < psb->m_nodes.size(); ++j)
+ {
+ // set NaN to zero;
+ if (m_dv[counter] != m_dv[counter])
+ {
+ m_dv[counter].setZero();
+ }
+ psb->m_nodes[j].m_v = m_backupVelocity[counter]+m_dv[counter];
+ psb->m_maxSpeedSquared = btMax(psb->m_maxSpeedSquared, psb->m_nodes[j].m_v.length2());
+ ++counter;
+ }
+ }
+}
+
+void btDeformableBodySolver::updateTempPosition()
+{
+ int counter = 0;
+ for (int i = 0; i < m_softBodies.size(); ++i)
+ {
+ btSoftBody* psb = m_softBodies[i];
+ if (!psb->isActive())
+ {
+ counter += psb->m_nodes.size();
+ continue;
+ }
+ for (int j = 0; j < psb->m_nodes.size(); ++j)
+ {
+ psb->m_nodes[j].m_q = psb->m_nodes[j].m_x + m_dt * psb->m_nodes[j].m_v;
+ ++counter;
+ }
+ psb->updateDeformation();
+ }
+}
+
+void btDeformableBodySolver::backupVelocity()
+{
+ int counter = 0;
+ for (int i = 0; i < m_softBodies.size(); ++i)
+ {
+ btSoftBody* psb = m_softBodies[i];
+ for (int j = 0; j < psb->m_nodes.size(); ++j)
+ {
+ m_backupVelocity[counter++] = psb->m_nodes[j].m_v;
+ }
+ }
+}
+
+void btDeformableBodySolver::setupDeformableSolve(bool implicit)
+{
+ int counter = 0;
+ for (int i = 0; i < m_softBodies.size(); ++i)
+ {
+ btSoftBody* psb = m_softBodies[i];
+ if (!psb->isActive())
+ {
+ counter += psb->m_nodes.size();
+ continue;
+ }
+ for (int j = 0; j < psb->m_nodes.size(); ++j)
+ {
+ if (implicit)
+ {
+ if ((psb->m_nodes[j].m_v - m_backupVelocity[counter]).norm() < SIMD_EPSILON)
+ m_dv[counter] = psb->m_nodes[j].m_v - m_backupVelocity[counter];
+ else
+ m_dv[counter] = psb->m_nodes[j].m_v - psb->m_nodes[j].m_vn;
+ m_backupVelocity[counter] = psb->m_nodes[j].m_vn;
+ }
+ else
+ m_dv[counter] = psb->m_nodes[j].m_v - m_backupVelocity[counter];
+ psb->m_nodes[j].m_v = m_backupVelocity[counter] + psb->m_nodes[j].m_vsplit;
+ ++counter;
+ }
+ }
+}
+
+void btDeformableBodySolver::revertVelocity()
+{
+ int counter = 0;
+ for (int i = 0; i < m_softBodies.size(); ++i)
+ {
+ btSoftBody* psb = m_softBodies[i];
+ for (int j = 0; j < psb->m_nodes.size(); ++j)
+ {
+ psb->m_nodes[j].m_v = m_backupVelocity[counter++];
+ }
+ }
+}
+
+bool btDeformableBodySolver::updateNodes()
+{
+ int numNodes = 0;
+ for (int i = 0; i < m_softBodies.size(); ++i)
+ numNodes += m_softBodies[i]->m_nodes.size();
+ if (numNodes != m_numNodes)
+ {
+ m_numNodes = numNodes;
+ return true;
+ }
+ return false;
+}
+
+
+void btDeformableBodySolver::predictMotion(btScalar solverdt)
+{
+ // apply explicit forces to velocity
+ m_objective->applyExplicitForce(m_residual);
+ for (int i = 0; i < m_softBodies.size(); ++i)
+ {
+ btSoftBody *psb = m_softBodies[i];
+
+ if (psb->isActive())
+ {
+ // predict motion for collision detection
+ predictDeformableMotion(psb, solverdt);
+ }
+ }
+}
+
+void btDeformableBodySolver::predictDeformableMotion(btSoftBody* psb, btScalar dt)
+{
+ int i, ni;
+
+ /* Update */
+ if (psb->m_bUpdateRtCst)
+ {
+ psb->m_bUpdateRtCst = false;
+ psb->updateConstants();
+ psb->m_fdbvt.clear();
+ if (psb->m_cfg.collisions & btSoftBody::fCollision::SDF_RD)
+ {
+ psb->initializeFaceTree();
+ }
+ }
+
+ /* Prepare */
+ psb->m_sst.sdt = dt * psb->m_cfg.timescale;
+ psb->m_sst.isdt = 1 / psb->m_sst.sdt;
+ psb->m_sst.velmrg = psb->m_sst.sdt * 3;
+ psb->m_sst.radmrg = psb->getCollisionShape()->getMargin();
+ psb->m_sst.updmrg = psb->m_sst.radmrg * (btScalar)0.25;
+ /* Bounds */
+ psb->updateBounds();
+
+ /* Integrate */
+ // do not allow particles to move more than the bounding box size
+ btScalar max_v = (psb->m_bounds[1]-psb->m_bounds[0]).norm() / dt;
+ for (i = 0, ni = psb->m_nodes.size(); i < ni; ++i)
+ {
+ btSoftBody::Node& n = psb->m_nodes[i];
+ // apply drag
+ n.m_v *= (1 - psb->m_cfg.drag);
+ // scale velocity back
+ if (n.m_v.norm() > max_v)
+ {
+ n.m_v.safeNormalize();
+ n.m_v *= max_v;
+ }
+ n.m_q = n.m_x + n.m_v * dt;
+ }
+
+ /* Nodes */
+ ATTRIBUTE_ALIGNED16(btDbvtVolume)
+ vol;
+ for (i = 0, ni = psb->m_nodes.size(); i < ni; ++i)
+ {
+ btSoftBody::Node& n = psb->m_nodes[i];
+ btVector3 points[2] = {n.m_x, n.m_q};
+ vol = btDbvtVolume::FromPoints(points, 2);
+ vol.Expand(btVector3(psb->m_sst.radmrg, psb->m_sst.radmrg, psb->m_sst.radmrg));
+ psb->m_ndbvt.update(n.m_leaf, vol);
+ }
+
+ if (!psb->m_fdbvt.empty())
+ {
+ for (int i = 0; i < psb->m_faces.size(); ++i)
+ {
+ btSoftBody::Face& f = psb->m_faces[i];
+ btVector3 points[6] = {f.m_n[0]->m_x, f.m_n[0]->m_q,
+ f.m_n[1]->m_x, f.m_n[1]->m_q,
+ f.m_n[2]->m_x, f.m_n[2]->m_q};
+ vol = btDbvtVolume::FromPoints(points, 6);
+ vol.Expand(btVector3(psb->m_sst.radmrg, psb->m_sst.radmrg, psb->m_sst.radmrg));
+ psb->m_fdbvt.update(f.m_leaf, vol);
+ }
+ }
+ /* Clear contacts */
+ psb->m_nodeRigidContacts.resize(0);
+ psb->m_faceRigidContacts.resize(0);
+ psb->m_faceNodeContacts.resize(0);
+ /* Optimize dbvt's */
+ psb->m_ndbvt.optimizeIncremental(1);
+ psb->m_fdbvt.optimizeIncremental(1);
+}
+
+
+void btDeformableBodySolver::updateSoftBodies()
+{
+ BT_PROFILE("updateSoftBodies");
+ for (int i = 0; i < m_softBodies.size(); i++)
+ {
+ btSoftBody *psb = (btSoftBody *)m_softBodies[i];
+ if (psb->isActive())
+ {
+ psb->updateNormals();
+ }
+ }
+}
+
+void btDeformableBodySolver::setImplicit(bool implicit)
+{
+ m_implicit = implicit;
+ m_objective->setImplicit(implicit);
+}
+
+void btDeformableBodySolver::setLineSearch(bool lineSearch)
+{
+ m_lineSearch = lineSearch;
+}
diff --git a/thirdparty/bullet/BulletSoftBody/btDeformableBodySolver.h b/thirdparty/bullet/BulletSoftBody/btDeformableBodySolver.h
new file mode 100644
index 0000000000..f78a8f696b
--- /dev/null
+++ b/thirdparty/bullet/BulletSoftBody/btDeformableBodySolver.h
@@ -0,0 +1,164 @@
+/*
+ Written by Xuchen Han <xuchenhan2015@u.northwestern.edu>
+
+ Bullet Continuous Collision Detection and Physics Library
+ Copyright (c) 2019 Google Inc. http://bulletphysics.org
+ 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.
+ */
+
+#ifndef BT_DEFORMABLE_BODY_SOLVERS_H
+#define BT_DEFORMABLE_BODY_SOLVERS_H
+
+
+#include "btSoftBodySolvers.h"
+#include "btDeformableBackwardEulerObjective.h"
+#include "btDeformableMultiBodyDynamicsWorld.h"
+#include "BulletDynamics/Featherstone/btMultiBodyLinkCollider.h"
+#include "BulletDynamics/Featherstone/btMultiBodyConstraint.h"
+
+struct btCollisionObjectWrapper;
+class btDeformableBackwardEulerObjective;
+class btDeformableMultiBodyDynamicsWorld;
+
+class btDeformableBodySolver : public btSoftBodySolver
+{
+ typedef btAlignedObjectArray<btVector3> TVStack;
+protected:
+ int m_numNodes; // total number of deformable body nodes
+ TVStack m_dv; // v_{n+1} - v_n
+ TVStack m_backup_dv; // backed up dv
+ TVStack m_ddv; // incremental dv
+ TVStack m_residual; // rhs of the linear solve
+ btAlignedObjectArray<btSoftBody *> m_softBodies; // all deformable bodies
+ TVStack m_backupVelocity; // backed up v, equals v_n for implicit, equals v_{n+1}^* for explicit
+ btScalar m_dt; // dt
+ btConjugateGradient<btDeformableBackwardEulerObjective> m_cg; // CG solver
+ bool m_implicit; // use implicit scheme if true, explicit scheme if false
+ int m_maxNewtonIterations; // max number of newton iterations
+ btScalar m_newtonTolerance; // stop newton iterations if f(x) < m_newtonTolerance
+ bool m_lineSearch; // If true, use newton's method with line search under implicit scheme
+
+public:
+ // handles data related to objective function
+ btDeformableBackwardEulerObjective* m_objective;
+
+ btDeformableBodySolver();
+
+ virtual ~btDeformableBodySolver();
+
+ virtual SolverTypes getSolverType() const
+ {
+ return DEFORMABLE_SOLVER;
+ }
+
+ // update soft body normals
+ virtual void updateSoftBodies();
+
+ // solve the momentum equation
+ virtual void solveDeformableConstraints(btScalar solverdt);
+
+ // solve the contact between deformable and rigid as well as among deformables
+ btScalar solveContactConstraints(btCollisionObject** deformableBodies,int numDeformableBodies);
+
+ // solve the position error between deformable and rigid as well as among deformables;
+ btScalar solveSplitImpulse(const btContactSolverInfo& infoGlobal);
+
+ // set up the position error in split impulse
+ void splitImpulseSetup(const btContactSolverInfo& infoGlobal);
+
+ // resize/clear data structures
+ void reinitialize(const btAlignedObjectArray<btSoftBody *>& softBodies, btScalar dt);
+
+ // set up contact constraints
+ void setConstraints();
+
+ // add in elastic forces and gravity to obtain v_{n+1}^* and calls predictDeformableMotion
+ virtual void predictMotion(btScalar solverdt);
+
+ // move to temporary position x_{n+1}^* = x_n + dt * v_{n+1}^*
+ // x_{n+1}^* is stored in m_q
+ void predictDeformableMotion(btSoftBody* psb, btScalar dt);
+
+ // save the current velocity to m_backupVelocity
+ void backupVelocity();
+
+ // set m_dv and m_backupVelocity to desired value to prepare for momentum solve
+ void setupDeformableSolve(bool implicit);
+
+ // set the current velocity to that backed up in m_backupVelocity
+ void revertVelocity();
+
+ // set velocity to m_dv + m_backupVelocity
+ void updateVelocity();
+
+ // update the node count
+ bool updateNodes();
+
+ // calculate the change in dv resulting from the momentum solve
+ void computeStep(TVStack& ddv, const TVStack& residual);
+
+ // calculate the change in dv resulting from the momentum solve when line search is turned on
+ btScalar computeDescentStep(TVStack& ddv, const TVStack& residual, bool verbose=false);
+
+ virtual void copySoftBodyToVertexBuffer(const btSoftBody *const softBody, btVertexBufferDescriptor *vertexBuffer) {}
+
+ // process collision between deformable and rigid
+ virtual void processCollision(btSoftBody * softBody, const btCollisionObjectWrapper * collisionObjectWrap)
+ {
+ softBody->defaultCollisionHandler(collisionObjectWrap);
+ }
+
+ // process collision between deformable and deformable
+ virtual void processCollision(btSoftBody * softBody, btSoftBody * otherSoftBody) {
+ softBody->defaultCollisionHandler(otherSoftBody);
+ }
+
+ // If true, implicit time stepping scheme is used.
+ // Otherwise, explicit time stepping scheme is used
+ void setImplicit(bool implicit);
+
+ // If true, newton's method with line search is used when implicit time stepping scheme is turned on
+ void setLineSearch(bool lineSearch);
+
+ // set temporary position x^* = x_n + dt * v
+ // update the deformation gradient at position x^*
+ void updateState();
+
+ // set dv = dv + scale * ddv
+ void updateDv(btScalar scale = 1);
+
+ // set temporary position x^* = x_n + dt * v^*
+ void updateTempPosition();
+
+ // save the current dv to m_backup_dv;
+ void backupDv();
+
+ // set dv to the backed-up value
+ void revertDv();
+
+ // set dv = dv + scale * ddv
+ // set v^* = v_n + dv
+ // set temporary position x^* = x_n + dt * v^*
+ // update the deformation gradient at position x^*
+ void updateEnergy(btScalar scale);
+
+ // calculates the appropriately scaled kinetic energy in the system, which is
+ // 1/2 * dv^T * M * dv
+ // used in line search
+ btScalar kineticEnergy();
+
+ // unused functions
+ virtual void optimize(btAlignedObjectArray<btSoftBody *> &softBodies, bool forceUpdate = false){}
+ virtual void solveConstraints(btScalar dt){}
+ virtual bool checkInitialized(){return true;}
+ virtual void copyBackToSoftBodies(bool bMove = true) {}
+};
+
+#endif /* btDeformableBodySolver_h */
diff --git a/thirdparty/bullet/BulletSoftBody/btDeformableContactConstraint.cpp b/thirdparty/bullet/BulletSoftBody/btDeformableContactConstraint.cpp
new file mode 100644
index 0000000000..e8219dc50e
--- /dev/null
+++ b/thirdparty/bullet/BulletSoftBody/btDeformableContactConstraint.cpp
@@ -0,0 +1,591 @@
+/*
+ Written by Xuchen Han <xuchenhan2015@u.northwestern.edu>
+
+ Bullet Continuous Collision Detection and Physics Library
+ Copyright (c) 2019 Google Inc. http://bulletphysics.org
+ 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.
+ */
+
+#include "btDeformableContactConstraint.h"
+/* ================ Deformable Node Anchor =================== */
+btDeformableNodeAnchorConstraint::btDeformableNodeAnchorConstraint(const btSoftBody::DeformableNodeRigidAnchor& a)
+: m_anchor(&a)
+, btDeformableContactConstraint(a.m_cti.m_normal)
+{
+}
+
+btDeformableNodeAnchorConstraint::btDeformableNodeAnchorConstraint(const btDeformableNodeAnchorConstraint& other)
+: m_anchor(other.m_anchor)
+, btDeformableContactConstraint(other)
+{
+}
+
+btVector3 btDeformableNodeAnchorConstraint::getVa() const
+{
+ const btSoftBody::sCti& cti = m_anchor->m_cti;
+ btVector3 va(0, 0, 0);
+ if (cti.m_colObj->hasContactResponse())
+ {
+ btRigidBody* rigidCol = 0;
+ btMultiBodyLinkCollider* multibodyLinkCol = 0;
+
+ // grab the velocity of the rigid body
+ if (cti.m_colObj->getInternalType() == btCollisionObject::CO_RIGID_BODY)
+ {
+ rigidCol = (btRigidBody*)btRigidBody::upcast(cti.m_colObj);
+ va = rigidCol ? (rigidCol->getVelocityInLocalPoint(m_anchor->m_c1)) : btVector3(0, 0, 0);
+ }
+ else if (cti.m_colObj->getInternalType() == btCollisionObject::CO_FEATHERSTONE_LINK)
+ {
+ multibodyLinkCol = (btMultiBodyLinkCollider*)btMultiBodyLinkCollider::upcast(cti.m_colObj);
+ if (multibodyLinkCol)
+ {
+ const int ndof = multibodyLinkCol->m_multiBody->getNumDofs() + 6;
+ const btScalar* J_n = &m_anchor->jacobianData_normal.m_jacobians[0];
+ const btScalar* J_t1 = &m_anchor->jacobianData_t1.m_jacobians[0];
+ const btScalar* J_t2 = &m_anchor->jacobianData_t2.m_jacobians[0];
+ const btScalar* local_v = multibodyLinkCol->m_multiBody->getVelocityVector();
+ const btScalar* local_dv = multibodyLinkCol->m_multiBody->getDeltaVelocityVector();
+ // add in the normal component of the va
+ btScalar vel = 0.0;
+ for (int k = 0; k < ndof; ++k)
+ {
+ vel += (local_v[k]+local_dv[k]) * J_n[k];
+ }
+ va = cti.m_normal * vel;
+ // add in the tangential components of the va
+ vel = 0.0;
+ for (int k = 0; k < ndof; ++k)
+ {
+ vel += (local_v[k]+local_dv[k]) * J_t1[k];
+ }
+ va += m_anchor->t1 * vel;
+ vel = 0.0;
+ for (int k = 0; k < ndof; ++k)
+ {
+ vel += (local_v[k]+local_dv[k]) * J_t2[k];
+ }
+ va += m_anchor->t2 * vel;
+ }
+ }
+ }
+ return va;
+}
+
+btScalar btDeformableNodeAnchorConstraint::solveConstraint()
+{
+ const btSoftBody::sCti& cti = m_anchor->m_cti;
+ btVector3 va = getVa();
+ btVector3 vb = getVb();
+ btVector3 vr = (vb - va);
+ // + (m_anchor->m_node->m_x - cti.m_colObj->getWorldTransform() * m_anchor->m_local) * 10.0
+ const btScalar dn = btDot(vr, cti.m_normal);
+ // dn is the normal component of velocity diffrerence. Approximates the residual. // todo xuchenhan@: this prob needs to be scaled by dt
+ btScalar residualSquare = dn*dn;
+ btVector3 impulse = m_anchor->m_c0 * vr;
+ // apply impulse to deformable nodes involved and change their velocities
+ applyImpulse(impulse);
+
+ // apply impulse to the rigid/multibodies involved and change their velocities
+ if (cti.m_colObj->getInternalType() == btCollisionObject::CO_RIGID_BODY)
+ {
+ btRigidBody* rigidCol = 0;
+ rigidCol = (btRigidBody*)btRigidBody::upcast(cti.m_colObj);
+ if (rigidCol)
+ {
+ rigidCol->applyImpulse(impulse, m_anchor->m_c1);
+ }
+ }
+ else if (cti.m_colObj->getInternalType() == btCollisionObject::CO_FEATHERSTONE_LINK)
+ {
+ btMultiBodyLinkCollider* multibodyLinkCol = 0;
+ multibodyLinkCol = (btMultiBodyLinkCollider*)btMultiBodyLinkCollider::upcast(cti.m_colObj);
+ if (multibodyLinkCol)
+ {
+ const btScalar* deltaV_normal = &m_anchor->jacobianData_normal.m_deltaVelocitiesUnitImpulse[0];
+ // apply normal component of the impulse
+ multibodyLinkCol->m_multiBody->applyDeltaVeeMultiDof2(deltaV_normal, impulse.dot(cti.m_normal));
+ // apply tangential component of the impulse
+ const btScalar* deltaV_t1 = &m_anchor->jacobianData_t1.m_deltaVelocitiesUnitImpulse[0];
+ multibodyLinkCol->m_multiBody->applyDeltaVeeMultiDof2(deltaV_t1, impulse.dot(m_anchor->t1));
+ const btScalar* deltaV_t2 = &m_anchor->jacobianData_t2.m_deltaVelocitiesUnitImpulse[0];
+ multibodyLinkCol->m_multiBody->applyDeltaVeeMultiDof2(deltaV_t2, impulse.dot(m_anchor->t2));
+ }
+ }
+ return residualSquare;
+}
+
+btVector3 btDeformableNodeAnchorConstraint::getVb() const
+{
+ return m_anchor->m_node->m_v;
+}
+
+void btDeformableNodeAnchorConstraint::applyImpulse(const btVector3& impulse)
+{
+ btVector3 dv = impulse * m_anchor->m_c2;
+ m_anchor->m_node->m_v -= dv;
+}
+
+/* ================ Deformable vs. Rigid =================== */
+btDeformableRigidContactConstraint::btDeformableRigidContactConstraint(const btSoftBody::DeformableRigidContact& c)
+: m_contact(&c)
+, btDeformableContactConstraint(c.m_cti.m_normal)
+{
+ m_total_normal_dv.setZero();
+ m_total_tangent_dv.setZero();
+ // penetration is non-positive. The magnitude of penetration is the depth of penetration.
+ m_penetration = btMin(btScalar(0), c.m_cti.m_offset);
+}
+
+btDeformableRigidContactConstraint::btDeformableRigidContactConstraint(const btDeformableRigidContactConstraint& other)
+: m_contact(other.m_contact)
+, btDeformableContactConstraint(other)
+, m_penetration(other.m_penetration)
+{
+ m_total_normal_dv = other.m_total_normal_dv;
+ m_total_tangent_dv = other.m_total_tangent_dv;
+}
+
+
+btVector3 btDeformableRigidContactConstraint::getVa() const
+{
+ const btSoftBody::sCti& cti = m_contact->m_cti;
+ btVector3 va(0, 0, 0);
+ if (cti.m_colObj->hasContactResponse())
+ {
+ btRigidBody* rigidCol = 0;
+ btMultiBodyLinkCollider* multibodyLinkCol = 0;
+
+ // grab the velocity of the rigid body
+ if (cti.m_colObj->getInternalType() == btCollisionObject::CO_RIGID_BODY)
+ {
+ rigidCol = (btRigidBody*)btRigidBody::upcast(cti.m_colObj);
+ va = rigidCol ? (rigidCol->getVelocityInLocalPoint(m_contact->m_c1)) : btVector3(0, 0, 0);
+ }
+ else if (cti.m_colObj->getInternalType() == btCollisionObject::CO_FEATHERSTONE_LINK)
+ {
+ multibodyLinkCol = (btMultiBodyLinkCollider*)btMultiBodyLinkCollider::upcast(cti.m_colObj);
+ if (multibodyLinkCol)
+ {
+ const int ndof = multibodyLinkCol->m_multiBody->getNumDofs() + 6;
+ const btScalar* J_n = &m_contact->jacobianData_normal.m_jacobians[0];
+ const btScalar* J_t1 = &m_contact->jacobianData_t1.m_jacobians[0];
+ const btScalar* J_t2 = &m_contact->jacobianData_t2.m_jacobians[0];
+ const btScalar* local_v = multibodyLinkCol->m_multiBody->getVelocityVector();
+ const btScalar* local_dv = multibodyLinkCol->m_multiBody->getDeltaVelocityVector();
+ // add in the normal component of the va
+ btScalar vel = 0.0;
+ for (int k = 0; k < ndof; ++k)
+ {
+ vel += (local_v[k]+local_dv[k]) * J_n[k];
+ }
+ va = cti.m_normal * vel;
+ // add in the tangential components of the va
+ vel = 0.0;
+ for (int k = 0; k < ndof; ++k)
+ {
+ vel += (local_v[k]+local_dv[k]) * J_t1[k];
+ }
+ va += m_contact->t1 * vel;
+ vel = 0.0;
+ for (int k = 0; k < ndof; ++k)
+ {
+ vel += (local_v[k]+local_dv[k]) * J_t2[k];
+ }
+ va += m_contact->t2 * vel;
+ }
+ }
+ }
+ return va;
+}
+
+btScalar btDeformableRigidContactConstraint::solveConstraint()
+{
+ const btSoftBody::sCti& cti = m_contact->m_cti;
+ btVector3 va = getVa();
+ btVector3 vb = getVb();
+ btVector3 vr = vb - va;
+ const btScalar dn = btDot(vr, cti.m_normal);
+ // dn is the normal component of velocity diffrerence. Approximates the residual. // todo xuchenhan@: this prob needs to be scaled by dt
+ btScalar residualSquare = dn*dn;
+ btVector3 impulse = m_contact->m_c0 * vr;
+ const btVector3 impulse_normal = m_contact->m_c0 * (cti.m_normal * dn);
+ btVector3 impulse_tangent = impulse - impulse_normal;
+ btVector3 old_total_tangent_dv = m_total_tangent_dv;
+ // m_c2 is the inverse mass of the deformable node/face
+ m_total_normal_dv -= impulse_normal * m_contact->m_c2;
+ m_total_tangent_dv -= impulse_tangent * m_contact->m_c2;
+
+ if (m_total_normal_dv.dot(cti.m_normal) < 0)
+ {
+ // separating in the normal direction
+ m_static = false;
+ m_total_tangent_dv = btVector3(0,0,0);
+ impulse_tangent.setZero();
+ }
+ else
+ {
+ if (m_total_normal_dv.norm() * m_contact->m_c3 < m_total_tangent_dv.norm())
+ {
+ // dynamic friction
+ // with dynamic friction, the impulse are still applied to the two objects colliding, however, it does not pose a constraint in the cg solve, hence the change to dv merely serves to update velocity in the contact iterations.
+ m_static = false;
+ if (m_total_tangent_dv.safeNorm() < SIMD_EPSILON)
+ {
+ m_total_tangent_dv = btVector3(0,0,0);
+ }
+ else
+ {
+ m_total_tangent_dv = m_total_tangent_dv.normalized() * m_total_normal_dv.safeNorm() * m_contact->m_c3;
+ }
+ impulse_tangent = -btScalar(1)/m_contact->m_c2 * (m_total_tangent_dv - old_total_tangent_dv);
+ }
+ else
+ {
+ // static friction
+ m_static = true;
+ }
+ }
+ impulse = impulse_normal + impulse_tangent;
+ // apply impulse to deformable nodes involved and change their velocities
+ applyImpulse(impulse);
+ // apply impulse to the rigid/multibodies involved and change their velocities
+ if (cti.m_colObj->getInternalType() == btCollisionObject::CO_RIGID_BODY)
+ {
+ btRigidBody* rigidCol = 0;
+ rigidCol = (btRigidBody*)btRigidBody::upcast(cti.m_colObj);
+ if (rigidCol)
+ {
+ rigidCol->applyImpulse(impulse, m_contact->m_c1);
+ }
+ }
+ else if (cti.m_colObj->getInternalType() == btCollisionObject::CO_FEATHERSTONE_LINK)
+ {
+ btMultiBodyLinkCollider* multibodyLinkCol = 0;
+ multibodyLinkCol = (btMultiBodyLinkCollider*)btMultiBodyLinkCollider::upcast(cti.m_colObj);
+ if (multibodyLinkCol)
+ {
+ const btScalar* deltaV_normal = &m_contact->jacobianData_normal.m_deltaVelocitiesUnitImpulse[0];
+ // apply normal component of the impulse
+ multibodyLinkCol->m_multiBody->applyDeltaVeeMultiDof2(deltaV_normal, impulse.dot(cti.m_normal));
+ if (impulse_tangent.norm() > SIMD_EPSILON)
+ {
+ // apply tangential component of the impulse
+ const btScalar* deltaV_t1 = &m_contact->jacobianData_t1.m_deltaVelocitiesUnitImpulse[0];
+ multibodyLinkCol->m_multiBody->applyDeltaVeeMultiDof2(deltaV_t1, impulse.dot(m_contact->t1));
+ const btScalar* deltaV_t2 = &m_contact->jacobianData_t2.m_deltaVelocitiesUnitImpulse[0];
+ multibodyLinkCol->m_multiBody->applyDeltaVeeMultiDof2(deltaV_t2, impulse.dot(m_contact->t2));
+ }
+ }
+ }
+ return residualSquare;
+}
+
+btScalar btDeformableRigidContactConstraint::solveSplitImpulse(const btContactSolverInfo& infoGlobal)
+{
+ const btSoftBody::sCti& cti = m_contact->m_cti;
+ const btScalar dn = m_penetration;
+ if (dn != 0)
+ {
+ const btVector3 impulse = (m_contact->m_c0 * (cti.m_normal * dn / infoGlobal.m_timeStep));
+ // one iteration of the position impulse corrects all the position error at this timestep
+ m_penetration -= dn;
+ // apply impulse to deformable nodes involved and change their position
+ applySplitImpulse(impulse);
+ // apply impulse to the rigid/multibodies involved and change their position
+ if (cti.m_colObj->getInternalType() == btCollisionObject::CO_RIGID_BODY)
+ {
+ btRigidBody* rigidCol = 0;
+ rigidCol = (btRigidBody*)btRigidBody::upcast(cti.m_colObj);
+ if (rigidCol)
+ {
+ rigidCol->applyPushImpulse(impulse, m_contact->m_c1);
+ }
+ }
+ else if (cti.m_colObj->getInternalType() == btCollisionObject::CO_FEATHERSTONE_LINK)
+ {
+ // todo xuchenhan@
+ }
+ return (m_penetration/infoGlobal.m_timeStep) * (m_penetration/infoGlobal.m_timeStep);
+ }
+ return 0;
+}
+
+/* ================ Node vs. Rigid =================== */
+btDeformableNodeRigidContactConstraint::btDeformableNodeRigidContactConstraint(const btSoftBody::DeformableNodeRigidContact& contact)
+ : m_node(contact.m_node)
+ , btDeformableRigidContactConstraint(contact)
+ {
+ }
+
+btDeformableNodeRigidContactConstraint::btDeformableNodeRigidContactConstraint(const btDeformableNodeRigidContactConstraint& other)
+: m_node(other.m_node)
+, btDeformableRigidContactConstraint(other)
+{
+}
+
+btVector3 btDeformableNodeRigidContactConstraint::getVb() const
+{
+ return m_node->m_v;
+}
+
+
+btVector3 btDeformableNodeRigidContactConstraint::getDv(const btSoftBody::Node* node) const
+{
+ return m_total_normal_dv + m_total_tangent_dv;
+}
+
+void btDeformableNodeRigidContactConstraint::applyImpulse(const btVector3& impulse)
+{
+ const btSoftBody::DeformableNodeRigidContact* contact = getContact();
+ btVector3 dv = impulse * contact->m_c2;
+ contact->m_node->m_v -= dv;
+}
+
+void btDeformableNodeRigidContactConstraint::applySplitImpulse(const btVector3& impulse)
+{
+ const btSoftBody::DeformableNodeRigidContact* contact = getContact();
+ btVector3 dv = impulse * contact->m_c2;
+ contact->m_node->m_vsplit -= dv;
+};
+
+/* ================ Face vs. Rigid =================== */
+btDeformableFaceRigidContactConstraint::btDeformableFaceRigidContactConstraint(const btSoftBody::DeformableFaceRigidContact& contact)
+: m_face(contact.m_face)
+, btDeformableRigidContactConstraint(contact)
+{
+}
+
+btDeformableFaceRigidContactConstraint::btDeformableFaceRigidContactConstraint(const btDeformableFaceRigidContactConstraint& other)
+: m_face(other.m_face)
+, btDeformableRigidContactConstraint(other)
+{
+}
+
+btVector3 btDeformableFaceRigidContactConstraint::getVb() const
+{
+ const btSoftBody::DeformableFaceRigidContact* contact = getContact();
+ btVector3 vb = m_face->m_n[0]->m_v * contact->m_bary[0] + m_face->m_n[1]->m_v * contact->m_bary[1] + m_face->m_n[2]->m_v * contact->m_bary[2];
+ return vb;
+}
+
+
+btVector3 btDeformableFaceRigidContactConstraint::getDv(const btSoftBody::Node* node) const
+{
+ btVector3 face_dv = m_total_normal_dv + m_total_tangent_dv;
+ const btSoftBody::DeformableFaceRigidContact* contact = getContact();
+ if (m_face->m_n[0] == node)
+ {
+ return face_dv * contact->m_weights[0];
+ }
+ if (m_face->m_n[1] == node)
+ {
+ return face_dv * contact->m_weights[1];
+ }
+ btAssert(node == m_face->m_n[2]);
+ return face_dv * contact->m_weights[2];
+}
+
+void btDeformableFaceRigidContactConstraint::applyImpulse(const btVector3& impulse)
+{
+ const btSoftBody::DeformableFaceRigidContact* contact = getContact();
+ btVector3 dv = impulse * contact->m_c2;
+ btSoftBody::Face* face = contact->m_face;
+
+ btVector3& v0 = face->m_n[0]->m_v;
+ btVector3& v1 = face->m_n[1]->m_v;
+ btVector3& v2 = face->m_n[2]->m_v;
+ const btScalar& im0 = face->m_n[0]->m_im;
+ const btScalar& im1 = face->m_n[1]->m_im;
+ const btScalar& im2 = face->m_n[2]->m_im;
+ if (im0 > 0)
+ v0 -= dv * contact->m_weights[0];
+ if (im1 > 0)
+ v1 -= dv * contact->m_weights[1];
+ if (im2 > 0)
+ v2 -= dv * contact->m_weights[2];
+
+ // apply strain limiting to prevent undamped modes
+ btScalar m01 = (btScalar(1)/(im0 + im1));
+ btScalar m02 = (btScalar(1)/(im0 + im2));
+ btScalar m12 = (btScalar(1)/(im1 + im2));
+
+ btVector3 dv0 = im0 * (m01 * (v1-v0) + m02 * (v2-v0));
+ btVector3 dv1 = im1 * (m01 * (v0-v1) + m12 * (v2-v1));
+ btVector3 dv2 = im2 * (m12 * (v1-v2) + m02 * (v0-v2));
+
+ v0 += dv0;
+ v1 += dv1;
+ v2 += dv2;
+}
+
+void btDeformableFaceRigidContactConstraint::applySplitImpulse(const btVector3& impulse)
+{
+ const btSoftBody::DeformableFaceRigidContact* contact = getContact();
+ btVector3 dv = impulse * contact->m_c2;
+ btSoftBody::Face* face = contact->m_face;
+
+ btVector3& v0 = face->m_n[0]->m_vsplit;
+ btVector3& v1 = face->m_n[1]->m_vsplit;
+ btVector3& v2 = face->m_n[2]->m_vsplit;
+ const btScalar& im0 = face->m_n[0]->m_im;
+ const btScalar& im1 = face->m_n[1]->m_im;
+ const btScalar& im2 = face->m_n[2]->m_im;
+ if (im0 > 0)
+ v0 -= dv * contact->m_weights[0];
+ if (im1 > 0)
+ v1 -= dv * contact->m_weights[1];
+ if (im2 > 0)
+ v2 -= dv * contact->m_weights[2];
+}
+
+/* ================ Face vs. Node =================== */
+btDeformableFaceNodeContactConstraint::btDeformableFaceNodeContactConstraint(const btSoftBody::DeformableFaceNodeContact& contact)
+: m_node(contact.m_node)
+, m_face(contact.m_face)
+, m_contact(&contact)
+, btDeformableContactConstraint(contact.m_normal)
+{
+ m_total_normal_dv.setZero();
+ m_total_tangent_dv.setZero();
+}
+
+btVector3 btDeformableFaceNodeContactConstraint::getVa() const
+{
+ return m_node->m_v;
+}
+
+btVector3 btDeformableFaceNodeContactConstraint::getVb() const
+{
+ const btSoftBody::DeformableFaceNodeContact* contact = getContact();
+ btVector3 vb = m_face->m_n[0]->m_v * contact->m_bary[0] + m_face->m_n[1]->m_v * contact->m_bary[1] + m_face->m_n[2]->m_v * contact->m_bary[2];
+ return vb;
+}
+
+btVector3 btDeformableFaceNodeContactConstraint::getDv(const btSoftBody::Node* n) const
+{
+ btVector3 dv = m_total_normal_dv + m_total_tangent_dv;
+ if (n == m_node)
+ return dv;
+ const btSoftBody::DeformableFaceNodeContact* contact = getContact();
+ if (m_face->m_n[0] == n)
+ {
+ return dv * contact->m_weights[0];
+ }
+ if (m_face->m_n[1] == n)
+ {
+ return dv * contact->m_weights[1];
+ }
+ btAssert(n == m_face->m_n[2]);
+ return dv * contact->m_weights[2];
+}
+
+btScalar btDeformableFaceNodeContactConstraint::solveConstraint()
+{
+ btVector3 va = getVa();
+ btVector3 vb = getVb();
+ btVector3 vr = vb - va;
+ const btScalar dn = btDot(vr, m_contact->m_normal);
+ // dn is the normal component of velocity diffrerence. Approximates the residual. // todo xuchenhan@: this prob needs to be scaled by dt
+ btScalar residualSquare = dn*dn;
+ btVector3 impulse = m_contact->m_c0 * vr;
+ const btVector3 impulse_normal = m_contact->m_c0 * (m_contact->m_normal * dn);
+ btVector3 impulse_tangent = impulse - impulse_normal;
+
+ btVector3 old_total_tangent_dv = m_total_tangent_dv;
+ // m_c2 is the inverse mass of the deformable node/face
+ if (m_node->m_im > 0)
+ {
+ m_total_normal_dv -= impulse_normal * m_node->m_im;
+ m_total_tangent_dv -= impulse_tangent * m_node->m_im;
+ }
+ else
+ {
+ m_total_normal_dv -= impulse_normal * m_contact->m_imf;
+ m_total_tangent_dv -= impulse_tangent * m_contact->m_imf;
+ }
+
+ if (m_total_normal_dv.dot(m_contact->m_normal) > 0)
+ {
+ // separating in the normal direction
+ m_static = false;
+ m_total_tangent_dv = btVector3(0,0,0);
+ impulse_tangent.setZero();
+ }
+ else
+ {
+ if (m_total_normal_dv.norm() * m_contact->m_friction < m_total_tangent_dv.norm())
+ {
+ // dynamic friction
+ // with dynamic friction, the impulse are still applied to the two objects colliding, however, it does not pose a constraint in the cg solve, hence the change to dv merely serves to update velocity in the contact iterations.
+ m_static = false;
+ if (m_total_tangent_dv.safeNorm() < SIMD_EPSILON)
+ {
+ m_total_tangent_dv = btVector3(0,0,0);
+ }
+ else
+ {
+ m_total_tangent_dv = m_total_tangent_dv.normalized() * m_total_normal_dv.safeNorm() * m_contact->m_friction;
+ }
+ impulse_tangent = -btScalar(1)/m_node->m_im * (m_total_tangent_dv - old_total_tangent_dv);
+ }
+ else
+ {
+ // static friction
+ m_static = true;
+ }
+ }
+ impulse = impulse_normal + impulse_tangent;
+ // apply impulse to deformable nodes involved and change their velocities
+ applyImpulse(impulse);
+ return residualSquare;
+}
+
+void btDeformableFaceNodeContactConstraint::applyImpulse(const btVector3& impulse)
+{
+ const btSoftBody::DeformableFaceNodeContact* contact = getContact();
+ btVector3 dva = impulse * contact->m_node->m_im;
+ btVector3 dvb = impulse * contact->m_imf;
+ if (contact->m_node->m_im > 0)
+ {
+ contact->m_node->m_v += dva;
+ }
+
+ btSoftBody::Face* face = contact->m_face;
+ btVector3& v0 = face->m_n[0]->m_v;
+ btVector3& v1 = face->m_n[1]->m_v;
+ btVector3& v2 = face->m_n[2]->m_v;
+ const btScalar& im0 = face->m_n[0]->m_im;
+ const btScalar& im1 = face->m_n[1]->m_im;
+ const btScalar& im2 = face->m_n[2]->m_im;
+ if (im0 > 0)
+ {
+ v0 -= dvb * contact->m_weights[0];
+ }
+ if (im1 > 0)
+ {
+ v1 -= dvb * contact->m_weights[1];
+ }
+ if (im2 > 0)
+ {
+ v2 -= dvb * contact->m_weights[2];
+ }
+ // todo: Face node constraints needs more work
+// btScalar m01 = (btScalar(1)/(im0 + im1));
+// btScalar m02 = (btScalar(1)/(im0 + im2));
+// btScalar m12 = (btScalar(1)/(im1 + im2));
+//
+// btVector3 dv0 = im0 * (m01 * (v1-v0) + m02 * (v2-v0));
+// btVector3 dv1 = im1 * (m01 * (v0-v1) + m12 * (v2-v1));
+// btVector3 dv2 = im2 * (m12 * (v1-v2) + m02 * (v0-v2));
+// v0 += dv0;
+// v1 += dv1;
+// v2 += dv2;
+}
diff --git a/thirdparty/bullet/BulletSoftBody/btDeformableContactConstraint.h b/thirdparty/bullet/BulletSoftBody/btDeformableContactConstraint.h
new file mode 100644
index 0000000000..912119e7c3
--- /dev/null
+++ b/thirdparty/bullet/BulletSoftBody/btDeformableContactConstraint.h
@@ -0,0 +1,302 @@
+/*
+ Written by Xuchen Han <xuchenhan2015@u.northwestern.edu>
+
+ Bullet Continuous Collision Detection and Physics Library
+ Copyright (c) 2019 Google Inc. http://bulletphysics.org
+ 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.
+ */
+
+#ifndef BT_DEFORMABLE_CONTACT_CONSTRAINT_H
+#define BT_DEFORMABLE_CONTACT_CONSTRAINT_H
+#include "btSoftBody.h"
+
+// btDeformableContactConstraint is an abstract class specifying the method that each type of contact constraint needs to implement
+class btDeformableContactConstraint
+{
+public:
+ // True if the friction is static
+ // False if the friction is dynamic
+ bool m_static;
+
+ // normal of the contact
+ btVector3 m_normal;
+
+ btDeformableContactConstraint(const btVector3& normal): m_static(false), m_normal(normal)
+ {
+ }
+
+ btDeformableContactConstraint(bool isStatic, const btVector3& normal): m_static(isStatic), m_normal(normal)
+ {
+ }
+
+ btDeformableContactConstraint(const btDeformableContactConstraint& other)
+ : m_static(other.m_static)
+ , m_normal(other.m_normal)
+ {
+
+ }
+ btDeformableContactConstraint(){}
+
+ virtual ~btDeformableContactConstraint(){}
+
+ // solve the constraint with inelastic impulse and return the error, which is the square of normal component of velocity diffrerence
+ // the constraint is solved by calculating the impulse between object A and B in the contact and apply the impulse to both objects involved in the contact
+ virtual btScalar solveConstraint() = 0;
+
+ // solve the position error by applying an inelastic impulse that changes only the position (not velocity)
+ virtual btScalar solveSplitImpulse(const btContactSolverInfo& infoGlobal) = 0;
+
+ // get the velocity of the object A in the contact
+ virtual btVector3 getVa() const = 0;
+
+ // get the velocity of the object B in the contact
+ virtual btVector3 getVb() const = 0;
+
+ // get the velocity change of the soft body node in the constraint
+ virtual btVector3 getDv(const btSoftBody::Node*) const = 0;
+
+ // apply impulse to the soft body node and/or face involved
+ virtual void applyImpulse(const btVector3& impulse) = 0;
+
+ // apply position based impulse to the soft body node and/or face involved
+ virtual void applySplitImpulse(const btVector3& impulse) = 0;
+
+ // scale the penetration depth by erp
+ virtual void setPenetrationScale(btScalar scale) = 0;
+};
+
+//
+// Constraint that a certain node in the deformable objects cannot move
+class btDeformableStaticConstraint : public btDeformableContactConstraint
+{
+public:
+ const btSoftBody::Node* m_node;
+
+ btDeformableStaticConstraint(){}
+
+ btDeformableStaticConstraint(const btSoftBody::Node* node): m_node(node), btDeformableContactConstraint(false, btVector3(0,0,0))
+ {
+ }
+
+ btDeformableStaticConstraint(const btDeformableStaticConstraint& other)
+ : m_node(other.m_node)
+ , btDeformableContactConstraint(other)
+ {
+
+ }
+
+ virtual ~btDeformableStaticConstraint(){}
+
+ virtual btScalar solveConstraint()
+ {
+ return 0;
+ }
+
+ virtual btScalar solveSplitImpulse(const btContactSolverInfo& infoGlobal)
+ {
+ return 0;
+ }
+
+ virtual btVector3 getVa() const
+ {
+ return btVector3(0,0,0);
+ }
+
+ virtual btVector3 getVb() const
+ {
+ return btVector3(0,0,0);
+ }
+
+ virtual btVector3 getDv(const btSoftBody::Node* n) const
+ {
+ return btVector3(0,0,0);
+ }
+
+ virtual void applyImpulse(const btVector3& impulse){}
+ virtual void applySplitImpulse(const btVector3& impulse){}
+ virtual void setPenetrationScale(btScalar scale){}
+};
+
+//
+// Anchor Constraint between rigid and deformable node
+class btDeformableNodeAnchorConstraint : public btDeformableContactConstraint
+{
+public:
+ const btSoftBody::DeformableNodeRigidAnchor* m_anchor;
+
+ btDeformableNodeAnchorConstraint(){}
+ btDeformableNodeAnchorConstraint(const btSoftBody::DeformableNodeRigidAnchor& c);
+ btDeformableNodeAnchorConstraint(const btDeformableNodeAnchorConstraint& other);
+ virtual ~btDeformableNodeAnchorConstraint()
+ {
+ }
+ virtual btScalar solveConstraint();
+ virtual btScalar solveSplitImpulse(const btContactSolverInfo& infoGlobal)
+ {
+ // todo xuchenhan@
+ return 0;
+ }
+ // object A is the rigid/multi body, and object B is the deformable node/face
+ virtual btVector3 getVa() const;
+ // get the velocity of the deformable node in contact
+ virtual btVector3 getVb() const;
+ virtual btVector3 getDv(const btSoftBody::Node* n) const
+ {
+ return btVector3(0,0,0);
+ }
+ virtual void applyImpulse(const btVector3& impulse);
+ virtual void applySplitImpulse(const btVector3& impulse)
+ {
+ // todo xuchenhan@
+ };
+ virtual void setPenetrationScale(btScalar scale){}
+};
+
+
+//
+// Constraint between rigid/multi body and deformable objects
+class btDeformableRigidContactConstraint : public btDeformableContactConstraint
+{
+public:
+ btVector3 m_total_normal_dv;
+ btVector3 m_total_tangent_dv;
+ btScalar m_penetration;
+ const btSoftBody::DeformableRigidContact* m_contact;
+
+ btDeformableRigidContactConstraint(){}
+ btDeformableRigidContactConstraint(const btSoftBody::DeformableRigidContact& c);
+ btDeformableRigidContactConstraint(const btDeformableRigidContactConstraint& other);
+ virtual ~btDeformableRigidContactConstraint()
+ {
+ }
+
+ // object A is the rigid/multi body, and object B is the deformable node/face
+ virtual btVector3 getVa() const;
+
+ virtual btScalar solveConstraint();
+
+ virtual btScalar solveSplitImpulse(const btContactSolverInfo& infoGlobal);
+
+ virtual void setPenetrationScale(btScalar scale)
+ {
+ m_penetration *= scale;
+ }
+};
+
+//
+// Constraint between rigid/multi body and deformable objects nodes
+class btDeformableNodeRigidContactConstraint : public btDeformableRigidContactConstraint
+{
+public:
+ // the deformable node in contact
+ const btSoftBody::Node* m_node;
+
+ btDeformableNodeRigidContactConstraint(){}
+ btDeformableNodeRigidContactConstraint(const btSoftBody::DeformableNodeRigidContact& contact);
+ btDeformableNodeRigidContactConstraint(const btDeformableNodeRigidContactConstraint& other);
+
+ virtual ~btDeformableNodeRigidContactConstraint()
+ {
+ }
+
+ // get the velocity of the deformable node in contact
+ virtual btVector3 getVb() const;
+
+ // get the velocity change of the input soft body node in the constraint
+ virtual btVector3 getDv(const btSoftBody::Node*) const;
+
+ // cast the contact to the desired type
+ const btSoftBody::DeformableNodeRigidContact* getContact() const
+ {
+ return static_cast<const btSoftBody::DeformableNodeRigidContact*>(m_contact);
+ }
+
+ virtual void applyImpulse(const btVector3& impulse);
+ virtual void applySplitImpulse(const btVector3& impulse);
+};
+
+//
+// Constraint between rigid/multi body and deformable objects faces
+class btDeformableFaceRigidContactConstraint : public btDeformableRigidContactConstraint
+{
+public:
+ const btSoftBody::Face* m_face;
+ btDeformableFaceRigidContactConstraint(){}
+ btDeformableFaceRigidContactConstraint(const btSoftBody::DeformableFaceRigidContact& contact);
+ btDeformableFaceRigidContactConstraint(const btDeformableFaceRigidContactConstraint& other);
+
+ virtual ~btDeformableFaceRigidContactConstraint()
+ {
+ }
+
+ // get the velocity of the deformable face at the contact point
+ virtual btVector3 getVb() const;
+
+ // get the velocity change of the input soft body node in the constraint
+ virtual btVector3 getDv(const btSoftBody::Node*) const;
+
+ // cast the contact to the desired type
+ const btSoftBody::DeformableFaceRigidContact* getContact() const
+ {
+ return static_cast<const btSoftBody::DeformableFaceRigidContact*>(m_contact);
+ }
+
+ virtual void applyImpulse(const btVector3& impulse);
+ virtual void applySplitImpulse(const btVector3& impulse);
+};
+
+//
+// Constraint between deformable objects faces and deformable objects nodes
+class btDeformableFaceNodeContactConstraint : public btDeformableContactConstraint
+{
+public:
+ btSoftBody::Node* m_node;
+ btSoftBody::Face* m_face;
+ const btSoftBody::DeformableFaceNodeContact* m_contact;
+ btVector3 m_total_normal_dv;
+ btVector3 m_total_tangent_dv;
+
+ btDeformableFaceNodeContactConstraint(){}
+
+ btDeformableFaceNodeContactConstraint(const btSoftBody::DeformableFaceNodeContact& contact);
+
+ virtual ~btDeformableFaceNodeContactConstraint(){}
+
+ virtual btScalar solveConstraint();
+
+ virtual btScalar solveSplitImpulse(const btContactSolverInfo& infoGlobal)
+ {
+ // todo: xuchenhan@
+ return 0;
+ }
+
+ // get the velocity of the object A in the contact
+ virtual btVector3 getVa() const;
+
+ // get the velocity of the object B in the contact
+ virtual btVector3 getVb() const;
+
+ // get the velocity change of the input soft body node in the constraint
+ virtual btVector3 getDv(const btSoftBody::Node*) const;
+
+ // cast the contact to the desired type
+ const btSoftBody::DeformableFaceNodeContact* getContact() const
+ {
+ return static_cast<const btSoftBody::DeformableFaceNodeContact*>(m_contact);
+ }
+
+ virtual void applyImpulse(const btVector3& impulse);
+ virtual void applySplitImpulse(const btVector3& impulse)
+ {
+ // todo xuchenhan@
+ }
+ virtual void setPenetrationScale(btScalar scale){}
+};
+#endif /* BT_DEFORMABLE_CONTACT_CONSTRAINT_H */
diff --git a/thirdparty/bullet/BulletSoftBody/btDeformableContactProjection.cpp b/thirdparty/bullet/BulletSoftBody/btDeformableContactProjection.cpp
new file mode 100644
index 0000000000..5a4f3241b4
--- /dev/null
+++ b/thirdparty/bullet/BulletSoftBody/btDeformableContactProjection.cpp
@@ -0,0 +1,509 @@
+/*
+ Written by Xuchen Han <xuchenhan2015@u.northwestern.edu>
+
+ Bullet Continuous Collision Detection and Physics Library
+ Copyright (c) 2019 Google Inc. http://bulletphysics.org
+ 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.
+ */
+
+#include "btDeformableContactProjection.h"
+#include "btDeformableMultiBodyDynamicsWorld.h"
+#include <algorithm>
+#include <cmath>
+btScalar btDeformableContactProjection::update(btCollisionObject** deformableBodies,int numDeformableBodies)
+{
+ btScalar residualSquare = 0;
+ for (int i = 0; i < numDeformableBodies; ++i)
+ {
+ for (int j = 0; j < m_softBodies.size(); ++j)
+ {
+ btCollisionObject* psb = m_softBodies[j];
+ if (psb != deformableBodies[i])
+ {
+ continue;
+ }
+ for (int k = 0; k < m_nodeRigidConstraints[j].size(); ++k)
+ {
+ btDeformableNodeRigidContactConstraint& constraint = m_nodeRigidConstraints[j][k];
+ btScalar localResidualSquare = constraint.solveConstraint();
+ residualSquare = btMax(residualSquare, localResidualSquare);
+ }
+ for (int k = 0; k < m_nodeAnchorConstraints[j].size(); ++k)
+ {
+ btDeformableNodeAnchorConstraint& constraint = m_nodeAnchorConstraints[j][k];
+ btScalar localResidualSquare = constraint.solveConstraint();
+ residualSquare = btMax(residualSquare, localResidualSquare);
+ }
+ for (int k = 0; k < m_faceRigidConstraints[j].size(); ++k)
+ {
+ btDeformableFaceRigidContactConstraint& constraint = m_faceRigidConstraints[j][k];
+ btScalar localResidualSquare = constraint.solveConstraint();
+ residualSquare = btMax(residualSquare, localResidualSquare);
+ }
+ for (int k = 0; k < m_deformableConstraints[j].size(); ++k)
+ {
+ btDeformableFaceNodeContactConstraint& constraint = m_deformableConstraints[j][k];
+ btScalar localResidualSquare = constraint.solveConstraint();
+ residualSquare = btMax(residualSquare, localResidualSquare);
+ }
+ }
+ }
+ return residualSquare;
+}
+
+void btDeformableContactProjection::splitImpulseSetup(const btContactSolverInfo& infoGlobal)
+{
+ for (int i = 0; i < m_softBodies.size(); ++i)
+ {
+ // node constraints
+ for (int j = 0; j < m_nodeRigidConstraints[i].size(); ++j)
+ {
+ btDeformableNodeRigidContactConstraint& constraint = m_nodeRigidConstraints[i][j];
+ constraint.setPenetrationScale(infoGlobal.m_deformable_erp);
+ }
+ // face constraints
+ for (int j = 0; j < m_faceRigidConstraints[i].size(); ++j)
+ {
+ btDeformableFaceRigidContactConstraint& constraint = m_faceRigidConstraints[i][j];
+ constraint.setPenetrationScale(infoGlobal.m_deformable_erp);
+ }
+ }
+}
+
+btScalar btDeformableContactProjection::solveSplitImpulse(const btContactSolverInfo& infoGlobal)
+{
+ btScalar residualSquare = 0;
+ for (int i = 0; i < m_softBodies.size(); ++i)
+ {
+ // node constraints
+ for (int j = 0; j < m_nodeRigidConstraints[i].size(); ++j)
+ {
+ btDeformableNodeRigidContactConstraint& constraint = m_nodeRigidConstraints[i][j];
+ btScalar localResidualSquare = constraint.solveSplitImpulse(infoGlobal);
+ residualSquare = btMax(residualSquare, localResidualSquare);
+ }
+ // anchor constraints
+ for (int j = 0; j < m_nodeAnchorConstraints[i].size(); ++j)
+ {
+ btDeformableNodeAnchorConstraint& constraint = m_nodeAnchorConstraints[i][j];
+ btScalar localResidualSquare = constraint.solveSplitImpulse(infoGlobal);
+ residualSquare = btMax(residualSquare, localResidualSquare);
+ }
+ // face constraints
+ for (int j = 0; j < m_faceRigidConstraints[i].size(); ++j)
+ {
+ btDeformableFaceRigidContactConstraint& constraint = m_faceRigidConstraints[i][j];
+ btScalar localResidualSquare = constraint.solveSplitImpulse(infoGlobal);
+ residualSquare = btMax(residualSquare, localResidualSquare);
+ }
+
+ }
+ return residualSquare;
+}
+
+void btDeformableContactProjection::setConstraints()
+{
+ BT_PROFILE("setConstraints");
+ for (int i = 0; i < m_softBodies.size(); ++i)
+ {
+ btSoftBody* psb = m_softBodies[i];
+ if (!psb->isActive())
+ {
+ continue;
+ }
+
+ // set Dirichlet constraint
+ for (int j = 0; j < psb->m_nodes.size(); ++j)
+ {
+ if (psb->m_nodes[j].m_im == 0)
+ {
+ btDeformableStaticConstraint static_constraint(&psb->m_nodes[j]);
+ m_staticConstraints[i].push_back(static_constraint);
+ }
+ }
+
+ // set up deformable anchors
+ for (int j = 0; j < psb->m_deformableAnchors.size(); ++j)
+ {
+ btSoftBody::DeformableNodeRigidAnchor& anchor = psb->m_deformableAnchors[j];
+ // skip fixed points
+ if (anchor.m_node->m_im == 0)
+ {
+ continue;
+ }
+ anchor.m_c1 = anchor.m_cti.m_colObj->getWorldTransform().getBasis() * anchor.m_local;
+ btDeformableNodeAnchorConstraint constraint(anchor);
+ m_nodeAnchorConstraints[i].push_back(constraint);
+ }
+
+ // set Deformable Node vs. Rigid constraint
+ for (int j = 0; j < psb->m_nodeRigidContacts.size(); ++j)
+ {
+ const btSoftBody::DeformableNodeRigidContact& contact = psb->m_nodeRigidContacts[j];
+ // skip fixed points
+ if (contact.m_node->m_im == 0)
+ {
+ continue;
+ }
+ btDeformableNodeRigidContactConstraint constraint(contact);
+ btVector3 va = constraint.getVa();
+ btVector3 vb = constraint.getVb();
+ const btVector3 vr = vb - va;
+ const btSoftBody::sCti& cti = contact.m_cti;
+ const btScalar dn = btDot(vr, cti.m_normal);
+ if (dn < SIMD_EPSILON)
+ {
+ m_nodeRigidConstraints[i].push_back(constraint);
+ }
+ }
+
+ // set Deformable Face vs. Rigid constraint
+ for (int j = 0; j < psb->m_faceRigidContacts.size(); ++j)
+ {
+ const btSoftBody::DeformableFaceRigidContact& contact = psb->m_faceRigidContacts[j];
+ // skip fixed faces
+ if (contact.m_c2 == 0)
+ {
+ continue;
+ }
+ btDeformableFaceRigidContactConstraint constraint(contact);
+ btVector3 va = constraint.getVa();
+ btVector3 vb = constraint.getVb();
+ const btVector3 vr = vb - va;
+ const btSoftBody::sCti& cti = contact.m_cti;
+ const btScalar dn = btDot(vr, cti.m_normal);
+ if (dn < SIMD_EPSILON)
+ {
+ m_faceRigidConstraints[i].push_back(constraint);
+ }
+ }
+
+ // set Deformable Face vs. Deformable Node constraint
+ for (int j = 0; j < psb->m_faceNodeContacts.size(); ++j)
+ {
+ const btSoftBody::DeformableFaceNodeContact& contact = psb->m_faceNodeContacts[j];
+
+ btDeformableFaceNodeContactConstraint constraint(contact);
+ btVector3 va = constraint.getVa();
+ btVector3 vb = constraint.getVb();
+ const btVector3 vr = vb - va;
+ const btScalar dn = btDot(vr, contact.m_normal);
+ if (dn > -SIMD_EPSILON)
+ {
+ m_deformableConstraints[i].push_back(constraint);
+ }
+ }
+ }
+}
+
+void btDeformableContactProjection::project(TVStack& x)
+{
+ const int dim = 3;
+ for (int index = 0; index < m_projectionsDict.size(); ++index)
+ {
+ btAlignedObjectArray<btVector3>& projectionDirs = *m_projectionsDict.getAtIndex(index);
+ size_t i = m_projectionsDict.getKeyAtIndex(index).getUid1();
+ if (projectionDirs.size() >= dim)
+ {
+ // static node
+ x[i].setZero();
+ continue;
+ }
+ else if (projectionDirs.size() == 2)
+ {
+ btVector3 dir0 = projectionDirs[0];
+ btVector3 dir1 = projectionDirs[1];
+ btVector3 free_dir = btCross(dir0, dir1);
+ if (free_dir.safeNorm() < SIMD_EPSILON)
+ {
+ x[i] -= x[i].dot(dir0) * dir0;
+ x[i] -= x[i].dot(dir1) * dir1;
+ }
+ else
+ {
+ free_dir.normalize();
+ x[i] = x[i].dot(free_dir) * free_dir;
+ }
+ }
+ else
+ {
+ btAssert(projectionDirs.size() == 1);
+ btVector3 dir0 = projectionDirs[0];
+ x[i] -= x[i].dot(dir0) * dir0;
+ }
+ }
+}
+
+void btDeformableContactProjection::setProjection()
+{
+ btAlignedObjectArray<btVector3> units;
+ units.push_back(btVector3(1,0,0));
+ units.push_back(btVector3(0,1,0));
+ units.push_back(btVector3(0,0,1));
+ for (int i = 0; i < m_softBodies.size(); ++i)
+ {
+ btSoftBody* psb = m_softBodies[i];
+ if (!psb->isActive())
+ {
+ continue;
+ }
+ for (int j = 0; j < m_staticConstraints[i].size(); ++j)
+ {
+ int index = m_staticConstraints[i][j].m_node->index;
+ if (m_projectionsDict.find(index) == NULL)
+ {
+ m_projectionsDict.insert(index, units);
+ }
+ else
+ {
+ btAlignedObjectArray<btVector3>& projections = *m_projectionsDict[index];
+ for (int k = 0; k < 3; ++k)
+ {
+ projections.push_back(units[k]);
+ }
+ }
+ }
+ for (int j = 0; j < m_nodeAnchorConstraints[i].size(); ++j)
+ {
+ int index = m_nodeAnchorConstraints[i][j].m_anchor->m_node->index;
+ if (m_projectionsDict.find(index) == NULL)
+ {
+ m_projectionsDict.insert(index, units);
+ }
+ else
+ {
+ btAlignedObjectArray<btVector3>& projections = *m_projectionsDict[index];
+ for (int k = 0; k < 3; ++k)
+ {
+ projections.push_back(units[k]);
+ }
+ }
+ }
+ for (int j = 0; j < m_nodeRigidConstraints[i].size(); ++j)
+ {
+ int index = m_nodeRigidConstraints[i][j].m_node->index;
+ if (m_nodeRigidConstraints[i][j].m_static)
+ {
+ if (m_projectionsDict.find(index) == NULL)
+ {
+ m_projectionsDict.insert(index, units);
+ }
+ else
+ {
+ btAlignedObjectArray<btVector3>& projections = *m_projectionsDict[index];
+ for (int k = 0; k < 3; ++k)
+ {
+ projections.push_back(units[k]);
+ }
+ }
+ }
+ else
+ {
+ if (m_projectionsDict.find(index) == NULL)
+ {
+ btAlignedObjectArray<btVector3> projections;
+ projections.push_back(m_nodeRigidConstraints[i][j].m_normal);
+ m_projectionsDict.insert(index, projections);
+ }
+ else
+ {
+ btAlignedObjectArray<btVector3>& projections = *m_projectionsDict[index];
+ projections.push_back(m_nodeRigidConstraints[i][j].m_normal);
+ }
+ }
+ }
+ for (int j = 0; j < m_faceRigidConstraints[i].size(); ++j)
+ {
+ const btSoftBody::Face* face = m_faceRigidConstraints[i][j].m_face;
+ for (int k = 0; k < 3; ++k)
+ {
+ const btSoftBody::Node* node = face->m_n[k];
+ int index = node->index;
+ if (m_faceRigidConstraints[i][j].m_static)
+ {
+ if (m_projectionsDict.find(index) == NULL)
+ {
+ m_projectionsDict.insert(index, units);
+ }
+ else
+ {
+ btAlignedObjectArray<btVector3>& projections = *m_projectionsDict[index];
+ for (int k = 0; k < 3; ++k)
+ {
+ projections.push_back(units[k]);
+ }
+ }
+ }
+ else
+ {
+ if (m_projectionsDict.find(index) == NULL)
+ {
+ btAlignedObjectArray<btVector3> projections;
+ projections.push_back(m_faceRigidConstraints[i][j].m_normal);
+ m_projectionsDict.insert(index, projections);
+ }
+ else
+ {
+ btAlignedObjectArray<btVector3>& projections = *m_projectionsDict[index];
+ projections.push_back(m_faceRigidConstraints[i][j].m_normal);
+ }
+ }
+ }
+ }
+ for (int j = 0; j < m_deformableConstraints[i].size(); ++j)
+ {
+ const btSoftBody::Face* face = m_deformableConstraints[i][j].m_face;
+ for (int k = 0; k < 3; ++k)
+ {
+ const btSoftBody::Node* node = face->m_n[k];
+ int index = node->index;
+ if (m_deformableConstraints[i][j].m_static)
+ {
+ if (m_projectionsDict.find(index) == NULL)
+ {
+ m_projectionsDict.insert(index, units);
+ }
+ else
+ {
+ btAlignedObjectArray<btVector3>& projections = *m_projectionsDict[index];
+ for (int k = 0; k < 3; ++k)
+ {
+ projections.push_back(units[k]);
+ }
+ }
+ }
+ else
+ {
+ if (m_projectionsDict.find(index) == NULL)
+ {
+ btAlignedObjectArray<btVector3> projections;
+ projections.push_back(m_deformableConstraints[i][j].m_normal);
+ m_projectionsDict.insert(index, projections);
+ }
+ else
+ {
+ btAlignedObjectArray<btVector3>& projections = *m_projectionsDict[index];
+ projections.push_back(m_deformableConstraints[i][j].m_normal);
+ }
+ }
+ }
+
+ const btSoftBody::Node* node = m_deformableConstraints[i][j].m_node;
+ int index = node->index;
+ if (m_deformableConstraints[i][j].m_static)
+ {
+ if (m_projectionsDict.find(index) == NULL)
+ {
+ m_projectionsDict.insert(index, units);
+ }
+ else
+ {
+ btAlignedObjectArray<btVector3>& projections = *m_projectionsDict[index];
+ for (int k = 0; k < 3; ++k)
+ {
+ projections.push_back(units[k]);
+ }
+ }
+ }
+ else
+ {
+ if (m_projectionsDict.find(index) == NULL)
+ {
+ btAlignedObjectArray<btVector3> projections;
+ projections.push_back(m_deformableConstraints[i][j].m_normal);
+ m_projectionsDict.insert(index, projections);
+ }
+ else
+ {
+ btAlignedObjectArray<btVector3>& projections = *m_projectionsDict[index];
+ projections.push_back(m_deformableConstraints[i][j].m_normal);
+ }
+ }
+ }
+ }
+}
+
+
+void btDeformableContactProjection::applyDynamicFriction(TVStack& f)
+{
+ for (int i = 0; i < m_softBodies.size(); ++i)
+ {
+ for (int j = 0; j < m_nodeRigidConstraints[i].size(); ++j)
+ {
+ const btDeformableNodeRigidContactConstraint& constraint = m_nodeRigidConstraints[i][j];
+ const btSoftBody::Node* node = constraint.m_node;
+ if (node->m_im != 0)
+ {
+ int index = node->index;
+ f[index] += constraint.getDv(node)* (1./node->m_im);
+ }
+ }
+ for (int j = 0; j < m_faceRigidConstraints[i].size(); ++j)
+ {
+ const btDeformableFaceRigidContactConstraint& constraint = m_faceRigidConstraints[i][j];
+ const btSoftBody::Face* face = constraint.getContact()->m_face;
+ for (int k = 0; k < 3; ++k)
+ {
+ const btSoftBody::Node* node = face->m_n[k];
+ if (node->m_im != 0)
+ {
+ int index = node->index;
+ f[index] += constraint.getDv(node)* (1./node->m_im);
+ }
+ }
+ }
+ for (int j = 0; j < m_deformableConstraints[i].size(); ++j)
+ {
+ const btDeformableFaceNodeContactConstraint& constraint = m_deformableConstraints[i][j];
+ const btSoftBody::Face* face = constraint.getContact()->m_face;
+ const btSoftBody::Node* node = constraint.getContact()->m_node;
+ if (node->m_im != 0)
+ {
+ int index = node->index;
+ f[index] += constraint.getDv(node)* (1./node->m_im);
+ }
+ for (int k = 0; k < 3; ++k)
+ {
+ const btSoftBody::Node* node = face->m_n[k];
+ if (node->m_im != 0)
+ {
+ int index = node->index;
+ f[index] += constraint.getDv(node)* (1./node->m_im);
+ }
+ }
+ }
+ }
+}
+
+void btDeformableContactProjection::reinitialize(bool nodeUpdated)
+{
+ int N = m_softBodies.size();
+ if (nodeUpdated)
+ {
+ m_staticConstraints.resize(N);
+ m_nodeAnchorConstraints.resize(N);
+ m_nodeRigidConstraints.resize(N);
+ m_faceRigidConstraints.resize(N);
+ m_deformableConstraints.resize(N);
+
+ }
+ for (int i = 0 ; i < N; ++i)
+ {
+ m_staticConstraints[i].clear();
+ m_nodeAnchorConstraints[i].clear();
+ m_nodeRigidConstraints[i].clear();
+ m_faceRigidConstraints[i].clear();
+ m_deformableConstraints[i].clear();
+ }
+ m_projectionsDict.clear();
+}
+
+
+
diff --git a/thirdparty/bullet/BulletSoftBody/btDeformableContactProjection.h b/thirdparty/bullet/BulletSoftBody/btDeformableContactProjection.h
new file mode 100644
index 0000000000..3c4490765e
--- /dev/null
+++ b/thirdparty/bullet/BulletSoftBody/btDeformableContactProjection.h
@@ -0,0 +1,90 @@
+/*
+ Written by Xuchen Han <xuchenhan2015@u.northwestern.edu>
+
+ Bullet Continuous Collision Detection and Physics Library
+ Copyright (c) 2019 Google Inc. http://bulletphysics.org
+ 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.
+ */
+
+#ifndef BT_CONTACT_PROJECTION_H
+#define BT_CONTACT_PROJECTION_H
+#include "btCGProjection.h"
+#include "btSoftBody.h"
+#include "BulletDynamics/Featherstone/btMultiBodyLinkCollider.h"
+#include "BulletDynamics/Featherstone/btMultiBodyConstraint.h"
+#include "btDeformableContactConstraint.h"
+#include "LinearMath/btHashMap.h"
+#include <vector>
+class btDeformableContactProjection
+{
+public:
+ typedef btAlignedObjectArray<btVector3> TVStack;
+ btAlignedObjectArray<btSoftBody *>& m_softBodies;
+
+// // map from node index to static constraint
+// btHashMap<btHashInt, btDeformableStaticConstraint> m_staticConstraints;
+// // map from node index to node rigid constraint
+// btHashMap<btHashInt, btAlignedObjectArray<btDeformableNodeRigidContactConstraint> > m_nodeRigidConstraints;
+// // map from node index to face rigid constraint
+// btHashMap<btHashInt, btAlignedObjectArray<btDeformableFaceRigidContactConstraint*> > m_faceRigidConstraints;
+// // map from node index to deformable constraint
+// btHashMap<btHashInt, btAlignedObjectArray<btDeformableFaceNodeContactConstraint*> > m_deformableConstraints;
+// // map from node index to node anchor constraint
+// btHashMap<btHashInt, btDeformableNodeAnchorConstraint> m_nodeAnchorConstraints;
+
+ // all constraints involving face
+ btAlignedObjectArray<btDeformableContactConstraint*> m_allFaceConstraints;
+
+ // map from node index to projection directions
+ btHashMap<btHashInt, btAlignedObjectArray<btVector3> > m_projectionsDict;
+
+ // map from node index to static constraint
+ btAlignedObjectArray<btAlignedObjectArray<btDeformableStaticConstraint> > m_staticConstraints;
+ // map from node index to node rigid constraint
+ btAlignedObjectArray<btAlignedObjectArray<btDeformableNodeRigidContactConstraint> > m_nodeRigidConstraints;
+ // map from node index to face rigid constraint
+ btAlignedObjectArray<btAlignedObjectArray<btDeformableFaceRigidContactConstraint> > m_faceRigidConstraints;
+ // map from node index to deformable constraint
+ btAlignedObjectArray<btAlignedObjectArray<btDeformableFaceNodeContactConstraint> > m_deformableConstraints;
+ // map from node index to node anchor constraint
+ btAlignedObjectArray<btAlignedObjectArray<btDeformableNodeAnchorConstraint> > m_nodeAnchorConstraints;
+
+ btDeformableContactProjection(btAlignedObjectArray<btSoftBody *>& softBodies)
+ : m_softBodies(softBodies)
+ {
+ }
+
+ virtual ~btDeformableContactProjection()
+ {
+ }
+
+ // apply the constraints to the rhs of the linear solve
+ virtual void project(TVStack& x);
+
+ // add friction force to the rhs of the linear solve
+ virtual void applyDynamicFriction(TVStack& f);
+
+ // update and solve the constraints
+ virtual btScalar update(btCollisionObject** deformableBodies,int numDeformableBodies);
+
+ // solve the position error using split impulse
+ virtual btScalar solveSplitImpulse(const btContactSolverInfo& infoGlobal);
+
+ // Add constraints to m_constraints. In addition, the constraints that each vertex own are recorded in m_constraintsDict.
+ virtual void setConstraints();
+
+ // Set up projections for each vertex by adding the projection direction to
+ virtual void setProjection();
+
+ virtual void reinitialize(bool nodeUpdated);
+
+ virtual void splitImpulseSetup(const btContactSolverInfo& infoGlobal);
+};
+#endif /* btDeformableContactProjection_h */
diff --git a/thirdparty/bullet/BulletSoftBody/btDeformableCorotatedForce.h b/thirdparty/bullet/BulletSoftBody/btDeformableCorotatedForce.h
new file mode 100644
index 0000000000..c2a26338e7
--- /dev/null
+++ b/thirdparty/bullet/BulletSoftBody/btDeformableCorotatedForce.h
@@ -0,0 +1,125 @@
+/*
+ Written by Xuchen Han <xuchenhan2015@u.northwestern.edu>
+
+ Bullet Continuous Collision Detection and Physics Library
+ Copyright (c) 2019 Google Inc. http://bulletphysics.org
+ 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.
+ */
+
+#ifndef BT_COROTATED_H
+#define BT_COROTATED_H
+
+#include "btDeformableLagrangianForce.h"
+#include "LinearMath/btPolarDecomposition.h"
+
+static inline int PolarDecomposition(const btMatrix3x3& m, btMatrix3x3& q, btMatrix3x3& s)
+{
+ static const btPolarDecomposition polar;
+ return polar.decompose(m, q, s);
+}
+
+class btDeformableCorotatedForce : public btDeformableLagrangianForce
+{
+public:
+ typedef btAlignedObjectArray<btVector3> TVStack;
+ btScalar m_mu, m_lambda;
+ btDeformableCorotatedForce(): m_mu(1), m_lambda(1)
+ {
+
+ }
+
+ btDeformableCorotatedForce(btScalar mu, btScalar lambda): m_mu(mu), m_lambda(lambda)
+ {
+ }
+
+ virtual void addScaledForces(btScalar scale, TVStack& force)
+ {
+ addScaledElasticForce(scale, force);
+ }
+
+ virtual void addScaledExplicitForce(btScalar scale, TVStack& force)
+ {
+ addScaledElasticForce(scale, force);
+ }
+
+ virtual void addScaledDampingForce(btScalar scale, TVStack& force)
+ {
+ }
+
+ virtual void addScaledElasticForce(btScalar scale, TVStack& force)
+ {
+ int numNodes = getNumNodes();
+ btAssert(numNodes <= force.size());
+ btVector3 grad_N_hat_1st_col = btVector3(-1,-1,-1);
+ for (int i = 0; i < m_softBodies.size(); ++i)
+ {
+ btSoftBody* psb = m_softBodies[i];
+ for (int j = 0; j < psb->m_tetras.size(); ++j)
+ {
+ btSoftBody::Tetra& tetra = psb->m_tetras[j];
+ btMatrix3x3 P;
+ firstPiola(tetra.m_F,P);
+ btVector3 force_on_node0 = P * (tetra.m_Dm_inverse.transpose()*grad_N_hat_1st_col);
+ btMatrix3x3 force_on_node123 = P * tetra.m_Dm_inverse.transpose();
+
+ btSoftBody::Node* node0 = tetra.m_n[0];
+ btSoftBody::Node* node1 = tetra.m_n[1];
+ btSoftBody::Node* node2 = tetra.m_n[2];
+ btSoftBody::Node* node3 = tetra.m_n[3];
+ size_t id0 = node0->index;
+ size_t id1 = node1->index;
+ size_t id2 = node2->index;
+ size_t id3 = node3->index;
+
+ // elastic force
+ // explicit elastic force
+ btScalar scale1 = scale * tetra.m_element_measure;
+ force[id0] -= scale1 * force_on_node0;
+ force[id1] -= scale1 * force_on_node123.getColumn(0);
+ force[id2] -= scale1 * force_on_node123.getColumn(1);
+ force[id3] -= scale1 * force_on_node123.getColumn(2);
+ }
+ }
+ }
+
+ void firstPiola(const btMatrix3x3& F, btMatrix3x3& P)
+ {
+ // btMatrix3x3 JFinvT = F.adjoint();
+ btScalar J = F.determinant();
+ P = F.adjoint().transpose() * (m_lambda * (J-1));
+ if (m_mu > SIMD_EPSILON)
+ {
+ btMatrix3x3 R,S;
+ if (J < 1024 * SIMD_EPSILON)
+ R.setIdentity();
+ else
+ PolarDecomposition(F, R, S); // this QR is not robust, consider using implicit shift svd
+ /*https://fuchuyuan.github.io/research/svd/paper.pdf*/
+ P += (F-R) * 2 * m_mu;
+ }
+ }
+
+ virtual void addScaledElasticForceDifferential(btScalar scale, const TVStack& dx, TVStack& df)
+ {
+ }
+
+ virtual void addScaledDampingForceDifferential(btScalar scale, const TVStack& dv, TVStack& df)
+ {
+ }
+
+ virtual btDeformableLagrangianForceType getForceType()
+ {
+ return BT_COROTATED_FORCE;
+ }
+
+};
+
+
+#endif /* btCorotated_h */
diff --git a/thirdparty/bullet/BulletSoftBody/btDeformableGravityForce.h b/thirdparty/bullet/BulletSoftBody/btDeformableGravityForce.h
new file mode 100644
index 0000000000..33e5a8564a
--- /dev/null
+++ b/thirdparty/bullet/BulletSoftBody/btDeformableGravityForce.h
@@ -0,0 +1,105 @@
+/*
+ Written by Xuchen Han <xuchenhan2015@u.northwestern.edu>
+
+ Bullet Continuous Collision Detection and Physics Library
+ Copyright (c) 2019 Google Inc. http://bulletphysics.org
+ 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.
+ */
+
+#ifndef BT_DEFORMABLE_GRAVITY_FORCE_H
+#define BT_DEFORMABLE_GRAVITY_FORCE_H
+
+#include "btDeformableLagrangianForce.h"
+
+class btDeformableGravityForce : public btDeformableLagrangianForce
+{
+public:
+ typedef btAlignedObjectArray<btVector3> TVStack;
+ btVector3 m_gravity;
+
+ btDeformableGravityForce(const btVector3& g) : m_gravity(g)
+ {
+ }
+
+ virtual void addScaledForces(btScalar scale, TVStack& force)
+ {
+ addScaledGravityForce(scale, force);
+ }
+
+ virtual void addScaledExplicitForce(btScalar scale, TVStack& force)
+ {
+ addScaledGravityForce(scale, force);
+ }
+
+ virtual void addScaledDampingForce(btScalar scale, TVStack& force)
+ {
+ }
+
+ virtual void addScaledElasticForceDifferential(btScalar scale, const TVStack& dx, TVStack& df)
+ {
+ }
+
+ virtual void addScaledDampingForceDifferential(btScalar scale, const TVStack& dv, TVStack& df)
+ {
+ }
+
+ virtual void addScaledGravityForce(btScalar scale, TVStack& force)
+ {
+ int numNodes = getNumNodes();
+ btAssert(numNodes <= force.size());
+ for (int i = 0; i < m_softBodies.size(); ++i)
+ {
+ btSoftBody* psb = m_softBodies[i];
+ if (!psb->isActive())
+ {
+ continue;
+ }
+ for (int j = 0; j < psb->m_nodes.size(); ++j)
+ {
+ btSoftBody::Node& n = psb->m_nodes[j];
+ size_t id = n.index;
+ btScalar mass = (n.m_im == 0) ? 0 : 1. / n.m_im;
+ btVector3 scaled_force = scale * m_gravity * mass;
+ force[id] += scaled_force;
+ }
+ }
+ }
+
+ virtual btDeformableLagrangianForceType getForceType()
+ {
+ return BT_GRAVITY_FORCE;
+ }
+
+ // the gravitational potential energy
+ virtual double totalEnergy(btScalar dt)
+ {
+ double e = 0;
+ for (int i = 0; i<m_softBodies.size();++i)
+ {
+ btSoftBody* psb = m_softBodies[i];
+ if (!psb->isActive())
+ {
+ continue;
+ }
+ for (int j = 0; j < psb->m_nodes.size(); ++j)
+ {
+ const btSoftBody::Node& node = psb->m_nodes[j];
+ if (node.m_im > 0)
+ {
+ e -= m_gravity.dot(node.m_q)/node.m_im;
+ }
+ }
+ }
+ return e;
+ }
+
+
+};
+#endif /* BT_DEFORMABLE_GRAVITY_FORCE_H */
diff --git a/thirdparty/bullet/BulletSoftBody/btDeformableLagrangianForce.h b/thirdparty/bullet/BulletSoftBody/btDeformableLagrangianForce.h
new file mode 100644
index 0000000000..64e80e23b3
--- /dev/null
+++ b/thirdparty/bullet/BulletSoftBody/btDeformableLagrangianForce.h
@@ -0,0 +1,364 @@
+/*
+ Written by Xuchen Han <xuchenhan2015@u.northwestern.edu>
+
+ Bullet Continuous Collision Detection and Physics Library
+ Copyright (c) 2019 Google Inc. http://bulletphysics.org
+ 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.
+ */
+
+#ifndef BT_DEFORMABLE_LAGRANGIAN_FORCE_H
+#define BT_DEFORMABLE_LAGRANGIAN_FORCE_H
+
+#include "btSoftBody.h"
+#include <LinearMath/btHashMap.h>
+#include <iostream>
+
+enum btDeformableLagrangianForceType
+{
+ BT_GRAVITY_FORCE = 1,
+ BT_MASSSPRING_FORCE = 2,
+ BT_COROTATED_FORCE = 3,
+ BT_NEOHOOKEAN_FORCE = 4,
+ BT_LINEAR_ELASTICITY_FORCE = 5
+};
+
+static inline double randomDouble(double low, double high)
+{
+ return low + static_cast<double>(rand()) / RAND_MAX * (high - low);
+}
+
+class btDeformableLagrangianForce
+{
+public:
+ typedef btAlignedObjectArray<btVector3> TVStack;
+ btAlignedObjectArray<btSoftBody *> m_softBodies;
+ const btAlignedObjectArray<btSoftBody::Node*>* m_nodes;
+
+ btDeformableLagrangianForce()
+ {
+ }
+
+ virtual ~btDeformableLagrangianForce(){}
+
+ // add all forces
+ virtual void addScaledForces(btScalar scale, TVStack& force) = 0;
+
+ // add damping df
+ virtual void addScaledDampingForceDifferential(btScalar scale, const TVStack& dv, TVStack& df) = 0;
+
+ // add elastic df
+ virtual void addScaledElasticForceDifferential(btScalar scale, const TVStack& dx, TVStack& df) = 0;
+
+ // add all forces that are explicit in explicit solve
+ virtual void addScaledExplicitForce(btScalar scale, TVStack& force) = 0;
+
+ // add all damping forces
+ virtual void addScaledDampingForce(btScalar scale, TVStack& force) = 0;
+
+ virtual btDeformableLagrangianForceType getForceType() = 0;
+
+ virtual void reinitialize(bool nodeUpdated)
+ {
+ }
+
+ // get number of nodes that have the force
+ virtual int getNumNodes()
+ {
+ int numNodes = 0;
+ for (int i = 0; i < m_softBodies.size(); ++i)
+ {
+ numNodes += m_softBodies[i]->m_nodes.size();
+ }
+ return numNodes;
+ }
+
+ // add a soft body to be affected by the particular lagrangian force
+ virtual void addSoftBody(btSoftBody* psb)
+ {
+ m_softBodies.push_back(psb);
+ }
+
+ virtual void setIndices(const btAlignedObjectArray<btSoftBody::Node*>* nodes)
+ {
+ m_nodes = nodes;
+ }
+
+ // Calculate the incremental deformable generated from the input dx
+ virtual btMatrix3x3 Ds(int id0, int id1, int id2, int id3, const TVStack& dx)
+ {
+ btVector3 c1 = dx[id1] - dx[id0];
+ btVector3 c2 = dx[id2] - dx[id0];
+ btVector3 c3 = dx[id3] - dx[id0];
+ return btMatrix3x3(c1,c2,c3).transpose();
+ }
+
+ // Calculate the incremental deformable generated from the current velocity
+ virtual btMatrix3x3 DsFromVelocity(const btSoftBody::Node* n0, const btSoftBody::Node* n1, const btSoftBody::Node* n2, const btSoftBody::Node* n3)
+ {
+ btVector3 c1 = n1->m_v - n0->m_v;
+ btVector3 c2 = n2->m_v - n0->m_v;
+ btVector3 c3 = n3->m_v - n0->m_v;
+ return btMatrix3x3(c1,c2,c3).transpose();
+ }
+
+ // test for addScaledElasticForce function
+ virtual void testDerivative()
+ {
+ for (int i = 0; i<m_softBodies.size();++i)
+ {
+ btSoftBody* psb = m_softBodies[i];
+ for (int j = 0; j < psb->m_nodes.size(); ++j)
+ {
+ psb->m_nodes[j].m_q += btVector3(randomDouble(-.1, .1), randomDouble(-.1, .1), randomDouble(-.1, .1));
+ }
+ psb->updateDeformation();
+ }
+
+ TVStack dx;
+ dx.resize(getNumNodes());
+ TVStack dphi_dx;
+ dphi_dx.resize(dx.size());
+ for (int i =0; i < dphi_dx.size();++i)
+ {
+ dphi_dx[i].setZero();
+ }
+ addScaledForces(-1, dphi_dx);
+
+ // write down the current position
+ TVStack x;
+ x.resize(dx.size());
+ int counter = 0;
+ for (int i = 0; i<m_softBodies.size();++i)
+ {
+ btSoftBody* psb = m_softBodies[i];
+ for (int j = 0; j < psb->m_nodes.size(); ++j)
+ {
+ x[counter] = psb->m_nodes[j].m_q;
+ counter++;
+ }
+ }
+ counter = 0;
+
+ // populate dx with random vectors
+ for (int i = 0; i < dx.size(); ++i)
+ {
+ dx[i].setX(randomDouble(-1, 1));
+ dx[i].setY(randomDouble(-1, 1));
+ dx[i].setZ(randomDouble(-1, 1));
+ }
+
+ btAlignedObjectArray<double> errors;
+ for (int it = 0; it < 10; ++it)
+ {
+ for (int i = 0; i < dx.size(); ++i)
+ {
+ dx[i] *= 0.5;
+ }
+
+ // get dphi/dx * dx
+ double dphi = 0;
+ for (int i = 0; i < dx.size(); ++i)
+ {
+ dphi += dphi_dx[i].dot(dx[i]);
+ }
+
+
+ for (int i = 0; i<m_softBodies.size();++i)
+ {
+ btSoftBody* psb = m_softBodies[i];
+ for (int j = 0; j < psb->m_nodes.size(); ++j)
+ {
+ psb->m_nodes[j].m_q = x[counter] + dx[counter];
+ counter++;
+ }
+ psb->updateDeformation();
+ }
+ counter = 0;
+ double f1 = totalElasticEnergy(0);
+
+ for (int i = 0; i<m_softBodies.size();++i)
+ {
+ btSoftBody* psb = m_softBodies[i];
+ for (int j = 0; j < psb->m_nodes.size(); ++j)
+ {
+ psb->m_nodes[j].m_q = x[counter] - dx[counter];
+ counter++;
+ }
+ psb->updateDeformation();
+ }
+ counter = 0;
+
+ double f2 = totalElasticEnergy(0);
+
+ //restore m_q
+ for (int i = 0; i<m_softBodies.size();++i)
+ {
+ btSoftBody* psb = m_softBodies[i];
+ for (int j = 0; j < psb->m_nodes.size(); ++j)
+ {
+ psb->m_nodes[j].m_q = x[counter];
+ counter++;
+ }
+ psb->updateDeformation();
+ }
+ counter = 0;
+ double error = f1-f2-2*dphi;
+ errors.push_back(error);
+ std::cout << "Iteration = " << it <<", f1 = " << f1 << ", f2 = " << f2 << ", error = " << error << std::endl;
+ }
+ for (int i = 1; i < errors.size(); ++i)
+ {
+ std::cout << "Iteration = " << i << ", ratio = " << errors[i-1]/errors[i] << std::endl;
+ }
+ }
+
+ // test for addScaledElasticForce function
+ virtual void testHessian()
+ {
+ for (int i = 0; i<m_softBodies.size();++i)
+ {
+ btSoftBody* psb = m_softBodies[i];
+ for (int j = 0; j < psb->m_nodes.size(); ++j)
+ {
+ psb->m_nodes[j].m_q += btVector3(randomDouble(-.1, .1), randomDouble(-.1, .1), randomDouble(-.1, .1));
+ }
+ psb->updateDeformation();
+ }
+
+
+ TVStack dx;
+ dx.resize(getNumNodes());
+ TVStack df;
+ df.resize(dx.size());
+ TVStack f1;
+ f1.resize(dx.size());
+ TVStack f2;
+ f2.resize(dx.size());
+
+
+ // write down the current position
+ TVStack x;
+ x.resize(dx.size());
+ int counter = 0;
+ for (int i = 0; i<m_softBodies.size();++i)
+ {
+ btSoftBody* psb = m_softBodies[i];
+ for (int j = 0; j < psb->m_nodes.size(); ++j)
+ {
+ x[counter] = psb->m_nodes[j].m_q;
+ counter++;
+ }
+ }
+ counter = 0;
+
+ // populate dx with random vectors
+ for (int i = 0; i < dx.size(); ++i)
+ {
+ dx[i].setX(randomDouble(-1, 1));
+ dx[i].setY(randomDouble(-1, 1));
+ dx[i].setZ(randomDouble(-1, 1));
+ }
+
+ btAlignedObjectArray<double> errors;
+ for (int it = 0; it < 10; ++it)
+ {
+ for (int i = 0; i < dx.size(); ++i)
+ {
+ dx[i] *= 0.5;
+ }
+
+ // get df
+ for (int i =0; i < df.size();++i)
+ {
+ df[i].setZero();
+ f1[i].setZero();
+ f2[i].setZero();
+ }
+
+ //set df
+ addScaledElasticForceDifferential(-1, dx, df);
+
+ for (int i = 0; i<m_softBodies.size();++i)
+ {
+ btSoftBody* psb = m_softBodies[i];
+ for (int j = 0; j < psb->m_nodes.size(); ++j)
+ {
+ psb->m_nodes[j].m_q = x[counter] + dx[counter];
+ counter++;
+ }
+ psb->updateDeformation();
+ }
+ counter = 0;
+
+ //set f1
+ addScaledForces(-1, f1);
+
+ for (int i = 0; i<m_softBodies.size();++i)
+ {
+ btSoftBody* psb = m_softBodies[i];
+ for (int j = 0; j < psb->m_nodes.size(); ++j)
+ {
+ psb->m_nodes[j].m_q = x[counter] - dx[counter];
+ counter++;
+ }
+ psb->updateDeformation();
+ }
+ counter = 0;
+
+ //set f2
+ addScaledForces(-1, f2);
+
+ //restore m_q
+ for (int i = 0; i<m_softBodies.size();++i)
+ {
+ btSoftBody* psb = m_softBodies[i];
+ for (int j = 0; j < psb->m_nodes.size(); ++j)
+ {
+ psb->m_nodes[j].m_q = x[counter];
+ counter++;
+ }
+ psb->updateDeformation();
+ }
+ counter = 0;
+ double error = 0;
+ for (int i = 0; i < df.size();++i)
+ {
+ btVector3 error_vector = f1[i]-f2[i]-2*df[i];
+ error += error_vector.length2();
+ }
+ error = btSqrt(error);
+ errors.push_back(error);
+ std::cout << "Iteration = " << it << ", error = " << error << std::endl;
+ }
+ for (int i = 1; i < errors.size(); ++i)
+ {
+ std::cout << "Iteration = " << i << ", ratio = " << errors[i-1]/errors[i] << std::endl;
+ }
+ }
+
+ //
+ virtual double totalElasticEnergy(btScalar dt)
+ {
+ return 0;
+ }
+
+ //
+ virtual double totalDampingEnergy(btScalar dt)
+ {
+ return 0;
+ }
+
+ // total Energy takes dt as input because certain energies depend on dt
+ virtual double totalEnergy(btScalar dt)
+ {
+ return totalElasticEnergy(dt) + totalDampingEnergy(dt);
+ }
+};
+#endif /* BT_DEFORMABLE_LAGRANGIAN_FORCE */
diff --git a/thirdparty/bullet/BulletSoftBody/btDeformableLinearElasticityForce.h b/thirdparty/bullet/BulletSoftBody/btDeformableLinearElasticityForce.h
new file mode 100644
index 0000000000..106dc10ad6
--- /dev/null
+++ b/thirdparty/bullet/BulletSoftBody/btDeformableLinearElasticityForce.h
@@ -0,0 +1,340 @@
+/*
+ Written by Xuchen Han <xuchenhan2015@u.northwestern.edu>
+
+ Bullet Continuous Collision Detection and Physics Library
+ Copyright (c) 2019 Google Inc. http://bulletphysics.org
+ 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.
+ */
+
+#ifndef BT_LINEAR_ELASTICITY_H
+#define BT_LINEAR_ELASTICITY_H
+
+#include "btDeformableLagrangianForce.h"
+#include "LinearMath/btQuickprof.h"
+class btDeformableLinearElasticityForce : public btDeformableLagrangianForce
+{
+public:
+ typedef btAlignedObjectArray<btVector3> TVStack;
+ btScalar m_mu, m_lambda;
+ btScalar m_mu_damp, m_lambda_damp;
+ btDeformableLinearElasticityForce(): m_mu(1), m_lambda(1)
+ {
+ btScalar damping = 0.05;
+ m_mu_damp = damping * m_mu;
+ m_lambda_damp = damping * m_lambda;
+ }
+
+ btDeformableLinearElasticityForce(btScalar mu, btScalar lambda, btScalar damping = 0.05): m_mu(mu), m_lambda(lambda)
+ {
+ m_mu_damp = damping * m_mu;
+ m_lambda_damp = damping * m_lambda;
+ }
+
+ virtual void addScaledForces(btScalar scale, TVStack& force)
+ {
+ addScaledDampingForce(scale, force);
+ addScaledElasticForce(scale, force);
+ }
+
+ virtual void addScaledExplicitForce(btScalar scale, TVStack& force)
+ {
+ addScaledElasticForce(scale, force);
+ }
+
+ // The damping matrix is calculated using the time n state as described in https://www.math.ucla.edu/~jteran/papers/GSSJT15.pdf to allow line search
+ virtual void addScaledDampingForce(btScalar scale, TVStack& force)
+ {
+ if (m_mu_damp == 0 && m_lambda_damp == 0)
+ return;
+ int numNodes = getNumNodes();
+ btAssert(numNodes <= force.size());
+ btVector3 grad_N_hat_1st_col = btVector3(-1,-1,-1);
+ for (int i = 0; i < m_softBodies.size(); ++i)
+ {
+ btSoftBody* psb = m_softBodies[i];
+ if (!psb->isActive())
+ {
+ continue;
+ }
+ for (int j = 0; j < psb->m_tetras.size(); ++j)
+ {
+ btSoftBody::Tetra& tetra = psb->m_tetras[j];
+ btSoftBody::Node* node0 = tetra.m_n[0];
+ btSoftBody::Node* node1 = tetra.m_n[1];
+ btSoftBody::Node* node2 = tetra.m_n[2];
+ btSoftBody::Node* node3 = tetra.m_n[3];
+ size_t id0 = node0->index;
+ size_t id1 = node1->index;
+ size_t id2 = node2->index;
+ size_t id3 = node3->index;
+ btMatrix3x3 dF = DsFromVelocity(node0, node1, node2, node3) * tetra.m_Dm_inverse;
+ btMatrix3x3 I;
+ I.setIdentity();
+ btMatrix3x3 dP = (dF + dF.transpose()) * m_mu_damp + I * (dF[0][0]+dF[1][1]+dF[2][2]) * m_lambda_damp;
+ // firstPiolaDampingDifferential(psb->m_tetraScratchesTn[j], dF, dP);
+ btVector3 df_on_node0 = dP * (tetra.m_Dm_inverse.transpose()*grad_N_hat_1st_col);
+ btMatrix3x3 df_on_node123 = dP * tetra.m_Dm_inverse.transpose();
+
+ // damping force differential
+ btScalar scale1 = scale * tetra.m_element_measure;
+ force[id0] -= scale1 * df_on_node0;
+ force[id1] -= scale1 * df_on_node123.getColumn(0);
+ force[id2] -= scale1 * df_on_node123.getColumn(1);
+ force[id3] -= scale1 * df_on_node123.getColumn(2);
+ }
+ }
+ }
+
+ virtual double totalElasticEnergy(btScalar dt)
+ {
+ double energy = 0;
+ for (int i = 0; i < m_softBodies.size(); ++i)
+ {
+ btSoftBody* psb = m_softBodies[i];
+ if (!psb->isActive())
+ {
+ continue;
+ }
+ for (int j = 0; j < psb->m_tetraScratches.size(); ++j)
+ {
+ btSoftBody::Tetra& tetra = psb->m_tetras[j];
+ btSoftBody::TetraScratch& s = psb->m_tetraScratches[j];
+ energy += tetra.m_element_measure * elasticEnergyDensity(s);
+ }
+ }
+ return energy;
+ }
+
+ // The damping energy is formulated as in https://www.math.ucla.edu/~jteran/papers/GSSJT15.pdf to allow line search
+ virtual double totalDampingEnergy(btScalar dt)
+ {
+ double energy = 0;
+ int sz = 0;
+ for (int i = 0; i < m_softBodies.size(); ++i)
+ {
+ btSoftBody* psb = m_softBodies[i];
+ if (!psb->isActive())
+ {
+ continue;
+ }
+ for (int j = 0; j < psb->m_nodes.size(); ++j)
+ {
+ sz = btMax(sz, psb->m_nodes[j].index);
+ }
+ }
+ TVStack dampingForce;
+ dampingForce.resize(sz+1);
+ for (int i = 0; i < dampingForce.size(); ++i)
+ dampingForce[i].setZero();
+ addScaledDampingForce(0.5, dampingForce);
+ for (int i = 0; i < m_softBodies.size(); ++i)
+ {
+ btSoftBody* psb = m_softBodies[i];
+ for (int j = 0; j < psb->m_nodes.size(); ++j)
+ {
+ const btSoftBody::Node& node = psb->m_nodes[j];
+ energy -= dampingForce[node.index].dot(node.m_v) / dt;
+ }
+ }
+ return energy;
+ }
+
+ double elasticEnergyDensity(const btSoftBody::TetraScratch& s)
+ {
+ double density = 0;
+ btMatrix3x3 epsilon = (s.m_F + s.m_F.transpose()) * 0.5 - btMatrix3x3::getIdentity();
+ btScalar trace = epsilon[0][0] + epsilon[1][1] + epsilon[2][2];
+ density += m_mu * (epsilon[0].length2() + epsilon[1].length2() + epsilon[2].length2());
+ density += m_lambda * trace * trace * 0.5;
+ return density;
+ }
+
+ virtual void addScaledElasticForce(btScalar scale, TVStack& force)
+ {
+ int numNodes = getNumNodes();
+ btAssert(numNodes <= force.size());
+ btVector3 grad_N_hat_1st_col = btVector3(-1,-1,-1);
+ for (int i = 0; i < m_softBodies.size(); ++i)
+ {
+ btSoftBody* psb = m_softBodies[i];
+ if (!psb->isActive())
+ {
+ continue;
+ }
+ btScalar max_p = psb->m_cfg.m_maxStress;
+ for (int j = 0; j < psb->m_tetras.size(); ++j)
+ {
+ btSoftBody::Tetra& tetra = psb->m_tetras[j];
+ btMatrix3x3 P;
+ firstPiola(psb->m_tetraScratches[j],P);
+#if USE_SVD
+ if (max_p > 0)
+ {
+ // since we want to clamp the principal stress to max_p, we only need to
+ // calculate SVD when sigma_0^2 + sigma_1^2 + sigma_2^2 > max_p * max_p
+ btScalar trPTP = (P[0].length2() + P[1].length2() + P[2].length2());
+ if (trPTP > max_p * max_p)
+ {
+ btMatrix3x3 U, V;
+ btVector3 sigma;
+ singularValueDecomposition(P, U, sigma, V);
+ sigma[0] = btMin(sigma[0], max_p);
+ sigma[1] = btMin(sigma[1], max_p);
+ sigma[2] = btMin(sigma[2], max_p);
+ sigma[0] = btMax(sigma[0], -max_p);
+ sigma[1] = btMax(sigma[1], -max_p);
+ sigma[2] = btMax(sigma[2], -max_p);
+ btMatrix3x3 Sigma;
+ Sigma.setIdentity();
+ Sigma[0][0] = sigma[0];
+ Sigma[1][1] = sigma[1];
+ Sigma[2][2] = sigma[2];
+ P = U * Sigma * V.transpose();
+ }
+ }
+#endif
+ // btVector3 force_on_node0 = P * (tetra.m_Dm_inverse.transpose()*grad_N_hat_1st_col);
+ btMatrix3x3 force_on_node123 = P * tetra.m_Dm_inverse.transpose();
+ btVector3 force_on_node0 = force_on_node123 * grad_N_hat_1st_col;
+
+ btSoftBody::Node* node0 = tetra.m_n[0];
+ btSoftBody::Node* node1 = tetra.m_n[1];
+ btSoftBody::Node* node2 = tetra.m_n[2];
+ btSoftBody::Node* node3 = tetra.m_n[3];
+ size_t id0 = node0->index;
+ size_t id1 = node1->index;
+ size_t id2 = node2->index;
+ size_t id3 = node3->index;
+
+ // elastic force
+ btScalar scale1 = scale * tetra.m_element_measure;
+ force[id0] -= scale1 * force_on_node0;
+ force[id1] -= scale1 * force_on_node123.getColumn(0);
+ force[id2] -= scale1 * force_on_node123.getColumn(1);
+ force[id3] -= scale1 * force_on_node123.getColumn(2);
+ }
+ }
+ }
+
+ // The damping matrix is calculated using the time n state as described in https://www.math.ucla.edu/~jteran/papers/GSSJT15.pdf to allow line search
+ virtual void addScaledDampingForceDifferential(btScalar scale, const TVStack& dv, TVStack& df)
+ {
+ if (m_mu_damp == 0 && m_lambda_damp == 0)
+ return;
+ int numNodes = getNumNodes();
+ btAssert(numNodes <= df.size());
+ btVector3 grad_N_hat_1st_col = btVector3(-1,-1,-1);
+ for (int i = 0; i < m_softBodies.size(); ++i)
+ {
+ btSoftBody* psb = m_softBodies[i];
+ if (!psb->isActive())
+ {
+ continue;
+ }
+ for (int j = 0; j < psb->m_tetras.size(); ++j)
+ {
+ btSoftBody::Tetra& tetra = psb->m_tetras[j];
+ btSoftBody::Node* node0 = tetra.m_n[0];
+ btSoftBody::Node* node1 = tetra.m_n[1];
+ btSoftBody::Node* node2 = tetra.m_n[2];
+ btSoftBody::Node* node3 = tetra.m_n[3];
+ size_t id0 = node0->index;
+ size_t id1 = node1->index;
+ size_t id2 = node2->index;
+ size_t id3 = node3->index;
+ btMatrix3x3 dF = Ds(id0, id1, id2, id3, dv) * tetra.m_Dm_inverse;
+ btMatrix3x3 I;
+ I.setIdentity();
+ btMatrix3x3 dP = (dF + dF.transpose()) * m_mu_damp + I * (dF[0][0]+dF[1][1]+dF[2][2]) * m_lambda_damp;
+ // firstPiolaDampingDifferential(psb->m_tetraScratchesTn[j], dF, dP);
+ // btVector3 df_on_node0 = dP * (tetra.m_Dm_inverse.transpose()*grad_N_hat_1st_col);
+ btMatrix3x3 df_on_node123 = dP * tetra.m_Dm_inverse.transpose();
+ btVector3 df_on_node0 = df_on_node123 * grad_N_hat_1st_col;
+
+ // damping force differential
+ btScalar scale1 = scale * tetra.m_element_measure;
+ df[id0] -= scale1 * df_on_node0;
+ df[id1] -= scale1 * df_on_node123.getColumn(0);
+ df[id2] -= scale1 * df_on_node123.getColumn(1);
+ df[id3] -= scale1 * df_on_node123.getColumn(2);
+ }
+ }
+ }
+
+ virtual void addScaledElasticForceDifferential(btScalar scale, const TVStack& dx, TVStack& df)
+ {
+ int numNodes = getNumNodes();
+ btAssert(numNodes <= df.size());
+ btVector3 grad_N_hat_1st_col = btVector3(-1,-1,-1);
+ for (int i = 0; i < m_softBodies.size(); ++i)
+ {
+ btSoftBody* psb = m_softBodies[i];
+ if (!psb->isActive())
+ {
+ continue;
+ }
+ for (int j = 0; j < psb->m_tetras.size(); ++j)
+ {
+ btSoftBody::Tetra& tetra = psb->m_tetras[j];
+ btSoftBody::Node* node0 = tetra.m_n[0];
+ btSoftBody::Node* node1 = tetra.m_n[1];
+ btSoftBody::Node* node2 = tetra.m_n[2];
+ btSoftBody::Node* node3 = tetra.m_n[3];
+ size_t id0 = node0->index;
+ size_t id1 = node1->index;
+ size_t id2 = node2->index;
+ size_t id3 = node3->index;
+ btMatrix3x3 dF = Ds(id0, id1, id2, id3, dx) * tetra.m_Dm_inverse;
+ btMatrix3x3 dP;
+ firstPiolaDifferential(psb->m_tetraScratches[j], dF, dP);
+ // btVector3 df_on_node0 = dP * (tetra.m_Dm_inverse.transpose()*grad_N_hat_1st_col);
+ btMatrix3x3 df_on_node123 = dP * tetra.m_Dm_inverse.transpose();
+ btVector3 df_on_node0 = df_on_node123 * grad_N_hat_1st_col;
+
+ // elastic force differential
+ btScalar scale1 = scale * tetra.m_element_measure;
+ df[id0] -= scale1 * df_on_node0;
+ df[id1] -= scale1 * df_on_node123.getColumn(0);
+ df[id2] -= scale1 * df_on_node123.getColumn(1);
+ df[id3] -= scale1 * df_on_node123.getColumn(2);
+ }
+ }
+ }
+
+ void firstPiola(const btSoftBody::TetraScratch& s, btMatrix3x3& P)
+ {
+ btMatrix3x3 epsilon = (s.m_F + s.m_F.transpose()) * 0.5 - btMatrix3x3::getIdentity();
+ btScalar trace = epsilon[0][0] + epsilon[1][1] + epsilon[2][2];
+ P = epsilon * btScalar(2) * m_mu + btMatrix3x3::getIdentity() * m_lambda * trace;
+ }
+
+ // Let P be the first piola stress.
+ // This function calculates the dP = dP/dF * dF
+ void firstPiolaDifferential(const btSoftBody::TetraScratch& s, const btMatrix3x3& dF, btMatrix3x3& dP)
+ {
+ btScalar trace = (dF[0][0] + dF[1][1] + dF[2][2]);
+ dP = (dF + dF.transpose()) * m_mu + btMatrix3x3::getIdentity() * m_lambda * trace;
+ }
+
+ // Let Q be the damping stress.
+ // This function calculates the dP = dQ/dF * dF
+ void firstPiolaDampingDifferential(const btSoftBody::TetraScratch& s, const btMatrix3x3& dF, btMatrix3x3& dP)
+ {
+ btScalar trace = (dF[0][0] + dF[1][1] + dF[2][2]);
+ dP = (dF + dF.transpose()) * m_mu_damp + btMatrix3x3::getIdentity() * m_lambda_damp * trace;
+ }
+
+ virtual btDeformableLagrangianForceType getForceType()
+ {
+ return BT_LINEAR_ELASTICITY_FORCE;
+ }
+
+};
+#endif /* BT_LINEAR_ELASTICITY_H */
diff --git a/thirdparty/bullet/BulletSoftBody/btDeformableMassSpringForce.h b/thirdparty/bullet/BulletSoftBody/btDeformableMassSpringForce.h
new file mode 100644
index 0000000000..54b4e4481d
--- /dev/null
+++ b/thirdparty/bullet/BulletSoftBody/btDeformableMassSpringForce.h
@@ -0,0 +1,255 @@
+/*
+ Written by Xuchen Han <xuchenhan2015@u.northwestern.edu>
+
+ Bullet Continuous Collision Detection and Physics Library
+ Copyright (c) 2019 Google Inc. http://bulletphysics.org
+ 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.
+ */
+
+#ifndef BT_MASS_SPRING_H
+#define BT_MASS_SPRING_H
+
+#include "btDeformableLagrangianForce.h"
+
+class btDeformableMassSpringForce : public btDeformableLagrangianForce
+{
+ // If true, the damping force will be in the direction of the spring
+ // If false, the damping force will be in the direction of the velocity
+ bool m_momentum_conserving;
+ btScalar m_elasticStiffness, m_dampingStiffness, m_bendingStiffness;
+public:
+ typedef btAlignedObjectArray<btVector3> TVStack;
+ btDeformableMassSpringForce() : m_momentum_conserving(false), m_elasticStiffness(1), m_dampingStiffness(0.05)
+ {
+ }
+ btDeformableMassSpringForce(btScalar k, btScalar d, bool conserve_angular = true, double bending_k = -1) : m_momentum_conserving(conserve_angular), m_elasticStiffness(k), m_dampingStiffness(d), m_bendingStiffness(bending_k)
+ {
+ if (m_bendingStiffness < btScalar(0))
+ {
+ m_bendingStiffness = m_elasticStiffness;
+ }
+ }
+
+ virtual void addScaledForces(btScalar scale, TVStack& force)
+ {
+ addScaledDampingForce(scale, force);
+ addScaledElasticForce(scale, force);
+ }
+
+ virtual void addScaledExplicitForce(btScalar scale, TVStack& force)
+ {
+ addScaledElasticForce(scale, force);
+ }
+
+ virtual void addScaledDampingForce(btScalar scale, TVStack& force)
+ {
+ int numNodes = getNumNodes();
+ btAssert(numNodes <= force.size());
+ for (int i = 0; i < m_softBodies.size(); ++i)
+ {
+ const btSoftBody* psb = m_softBodies[i];
+ if (!psb->isActive())
+ {
+ continue;
+ }
+ for (int j = 0; j < psb->m_links.size(); ++j)
+ {
+ const btSoftBody::Link& link = psb->m_links[j];
+ btSoftBody::Node* node1 = link.m_n[0];
+ btSoftBody::Node* node2 = link.m_n[1];
+ size_t id1 = node1->index;
+ size_t id2 = node2->index;
+
+ // damping force
+ btVector3 v_diff = (node2->m_v - node1->m_v);
+ btVector3 scaled_force = scale * m_dampingStiffness * v_diff;
+ if (m_momentum_conserving)
+ {
+ if ((node2->m_x - node1->m_x).norm() > SIMD_EPSILON)
+ {
+ btVector3 dir = (node2->m_x - node1->m_x).normalized();
+ scaled_force = scale * m_dampingStiffness * v_diff.dot(dir) * dir;
+ }
+ }
+ force[id1] += scaled_force;
+ force[id2] -= scaled_force;
+ }
+ }
+ }
+
+ virtual void addScaledElasticForce(btScalar scale, TVStack& force)
+ {
+ int numNodes = getNumNodes();
+ btAssert(numNodes <= force.size());
+ for (int i = 0; i < m_softBodies.size(); ++i)
+ {
+ const btSoftBody* psb = m_softBodies[i];
+ if (!psb->isActive())
+ {
+ continue;
+ }
+ for (int j = 0; j < psb->m_links.size(); ++j)
+ {
+ const btSoftBody::Link& link = psb->m_links[j];
+ btSoftBody::Node* node1 = link.m_n[0];
+ btSoftBody::Node* node2 = link.m_n[1];
+ btScalar r = link.m_rl;
+ size_t id1 = node1->index;
+ size_t id2 = node2->index;
+
+ // elastic force
+ btVector3 dir = (node2->m_q - node1->m_q);
+ btVector3 dir_normalized = (dir.norm() > SIMD_EPSILON) ? dir.normalized() : btVector3(0,0,0);
+ btScalar scaled_stiffness = scale * (link.m_bbending ? m_bendingStiffness : m_elasticStiffness);
+ btVector3 scaled_force = scaled_stiffness * (dir - dir_normalized * r);
+ force[id1] += scaled_force;
+ force[id2] -= scaled_force;
+ }
+ }
+ }
+
+ virtual void addScaledDampingForceDifferential(btScalar scale, const TVStack& dv, TVStack& df)
+ {
+ // implicit damping force differential
+ for (int i = 0; i < m_softBodies.size(); ++i)
+ {
+ btSoftBody* psb = m_softBodies[i];
+ if (!psb->isActive())
+ {
+ continue;
+ }
+ btScalar scaled_k_damp = m_dampingStiffness * scale;
+ for (int j = 0; j < psb->m_links.size(); ++j)
+ {
+ const btSoftBody::Link& link = psb->m_links[j];
+ btSoftBody::Node* node1 = link.m_n[0];
+ btSoftBody::Node* node2 = link.m_n[1];
+ size_t id1 = node1->index;
+ size_t id2 = node2->index;
+
+ btVector3 local_scaled_df = scaled_k_damp * (dv[id2] - dv[id1]);
+ if (m_momentum_conserving)
+ {
+ if ((node2->m_x - node1->m_x).norm() > SIMD_EPSILON)
+ {
+ btVector3 dir = (node2->m_x - node1->m_x).normalized();
+ local_scaled_df= scaled_k_damp * (dv[id2] - dv[id1]).dot(dir) * dir;
+ }
+ }
+ df[id1] += local_scaled_df;
+ df[id2] -= local_scaled_df;
+ }
+ }
+ }
+
+ virtual double totalElasticEnergy(btScalar dt)
+ {
+ double energy = 0;
+ for (int i = 0; i < m_softBodies.size(); ++i)
+ {
+ const btSoftBody* psb = m_softBodies[i];
+ if (!psb->isActive())
+ {
+ continue;
+ }
+ for (int j = 0; j < psb->m_links.size(); ++j)
+ {
+ const btSoftBody::Link& link = psb->m_links[j];
+ btSoftBody::Node* node1 = link.m_n[0];
+ btSoftBody::Node* node2 = link.m_n[1];
+ btScalar r = link.m_rl;
+
+ // elastic force
+ btVector3 dir = (node2->m_q - node1->m_q);
+ energy += 0.5 * m_elasticStiffness * (dir.norm() - r) * (dir.norm() -r);
+ }
+ }
+ return energy;
+ }
+
+ virtual double totalDampingEnergy(btScalar dt)
+ {
+ double energy = 0;
+ int sz = 0;
+ for (int i = 0; i < m_softBodies.size(); ++i)
+ {
+ btSoftBody* psb = m_softBodies[i];
+ if (!psb->isActive())
+ {
+ continue;
+ }
+ for (int j = 0; j < psb->m_nodes.size(); ++j)
+ {
+ sz = btMax(sz, psb->m_nodes[j].index);
+ }
+ }
+ TVStack dampingForce;
+ dampingForce.resize(sz+1);
+ for (int i = 0; i < dampingForce.size(); ++i)
+ dampingForce[i].setZero();
+ addScaledDampingForce(0.5, dampingForce);
+ for (int i = 0; i < m_softBodies.size(); ++i)
+ {
+ btSoftBody* psb = m_softBodies[i];
+ for (int j = 0; j < psb->m_nodes.size(); ++j)
+ {
+ const btSoftBody::Node& node = psb->m_nodes[j];
+ energy -= dampingForce[node.index].dot(node.m_v) / dt;
+ }
+ }
+ return energy;
+ }
+
+ virtual void addScaledElasticForceDifferential(btScalar scale, const TVStack& dx, TVStack& df)
+ {
+ // implicit damping force differential
+ for (int i = 0; i < m_softBodies.size(); ++i)
+ {
+ const btSoftBody* psb = m_softBodies[i];
+ if (!psb->isActive())
+ {
+ continue;
+ }
+ for (int j = 0; j < psb->m_links.size(); ++j)
+ {
+ const btSoftBody::Link& link = psb->m_links[j];
+ btSoftBody::Node* node1 = link.m_n[0];
+ btSoftBody::Node* node2 = link.m_n[1];
+ size_t id1 = node1->index;
+ size_t id2 = node2->index;
+ btScalar r = link.m_rl;
+
+ btVector3 dir = (node1->m_q - node2->m_q);
+ btScalar dir_norm = dir.norm();
+ btVector3 dir_normalized = (dir_norm > SIMD_EPSILON) ? dir.normalized() : btVector3(0,0,0);
+ btVector3 dx_diff = dx[id1] - dx[id2];
+ btVector3 scaled_df = btVector3(0,0,0);
+ btScalar scaled_k = scale * (link.m_bbending ? m_bendingStiffness : m_elasticStiffness);
+ if (dir_norm > SIMD_EPSILON)
+ {
+ scaled_df -= scaled_k * dir_normalized.dot(dx_diff) * dir_normalized;
+ scaled_df += scaled_k * dir_normalized.dot(dx_diff) * ((dir_norm-r)/dir_norm) * dir_normalized;
+ scaled_df -= scaled_k * ((dir_norm-r)/dir_norm) * dx_diff;
+ }
+
+ df[id1] += scaled_df;
+ df[id2] -= scaled_df;
+ }
+ }
+ }
+
+ virtual btDeformableLagrangianForceType getForceType()
+ {
+ return BT_MASSSPRING_FORCE;
+ }
+
+};
+
+#endif /* btMassSpring_h */
diff --git a/thirdparty/bullet/BulletSoftBody/btDeformableMultiBodyConstraintSolver.cpp b/thirdparty/bullet/BulletSoftBody/btDeformableMultiBodyConstraintSolver.cpp
new file mode 100644
index 0000000000..06f95d69f6
--- /dev/null
+++ b/thirdparty/bullet/BulletSoftBody/btDeformableMultiBodyConstraintSolver.cpp
@@ -0,0 +1,143 @@
+/*
+ Written by Xuchen Han <xuchenhan2015@u.northwestern.edu>
+
+ Bullet Continuous Collision Detection and Physics Library
+ Copyright (c) 2019 Google Inc. http://bulletphysics.org
+ 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.
+ */
+
+
+#include "btDeformableMultiBodyConstraintSolver.h"
+#include <iostream>
+// override the iterations method to include deformable/multibody contact
+btScalar btDeformableMultiBodyConstraintSolver::solveDeformableGroupIterations(btCollisionObject** bodies,int numBodies,btCollisionObject** deformableBodies,int numDeformableBodies,btPersistentManifold** manifoldPtr, int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& infoGlobal,btIDebugDraw* debugDrawer)
+{
+ {
+ ///this is a special step to resolve penetrations (just for contacts)
+ solveGroupCacheFriendlySplitImpulseIterations(bodies, numBodies, manifoldPtr, numManifolds, constraints, numConstraints, infoGlobal, debugDrawer);
+
+ int maxIterations = m_maxOverrideNumSolverIterations > infoGlobal.m_numIterations ? m_maxOverrideNumSolverIterations : infoGlobal.m_numIterations;
+ for (int iteration = 0; iteration < maxIterations; iteration++)
+ {
+ // rigid bodies are solved using solver body velocity, but rigid/deformable contact directly uses the velocity of the actual rigid body. So we have to do the following: Solve one iteration of the rigid/rigid contact, get the updated velocity in the solver body and update the velocity of the underlying rigid body. Then solve the rigid/deformable contact. Finally, grab the (once again) updated rigid velocity and update the velocity of the wrapping solver body
+
+ // solve rigid/rigid in solver body
+ m_leastSquaresResidual = solveSingleIteration(iteration, bodies, numBodies, manifoldPtr, numManifolds, constraints, numConstraints, infoGlobal, debugDrawer);
+ // solver body velocity -> rigid body velocity
+ solverBodyWriteBack(infoGlobal);
+ btScalar deformableResidual = m_deformableSolver->solveContactConstraints(deformableBodies,numDeformableBodies);
+ // update rigid body velocity in rigid/deformable contact
+ m_leastSquaresResidual = btMax(m_leastSquaresResidual, deformableResidual);
+ // solver body velocity <- rigid body velocity
+ writeToSolverBody(bodies, numBodies, infoGlobal);
+
+ if (m_leastSquaresResidual <= infoGlobal.m_leastSquaresResidualThreshold || (iteration >= (maxIterations - 1)))
+ {
+#ifdef VERBOSE_RESIDUAL_PRINTF
+ printf("residual = %f at iteration #%d\n", m_leastSquaresResidual, iteration);
+#endif
+ m_analyticsData.m_numSolverCalls++;
+ m_analyticsData.m_numIterationsUsed = iteration+1;
+ m_analyticsData.m_islandId = -2;
+ if (numBodies>0)
+ m_analyticsData.m_islandId = bodies[0]->getCompanionId();
+ m_analyticsData.m_numBodies = numBodies;
+ m_analyticsData.m_numContactManifolds = numManifolds;
+ m_analyticsData.m_remainingLeastSquaresResidual = m_leastSquaresResidual;
+ break;
+ }
+ }
+ }
+ return 0.f;
+}
+
+void btDeformableMultiBodyConstraintSolver::solveDeformableBodyGroup(btCollisionObject * *bodies, int numBodies, btCollisionObject * *deformableBodies, int numDeformableBodies, btPersistentManifold** manifold, int numManifolds, btTypedConstraint** constraints, int numConstraints, btMultiBodyConstraint** multiBodyConstraints, int numMultiBodyConstraints, const btContactSolverInfo& info, btIDebugDraw* debugDrawer, btDispatcher* dispatcher)
+{
+ m_tmpMultiBodyConstraints = multiBodyConstraints;
+ m_tmpNumMultiBodyConstraints = numMultiBodyConstraints;
+
+ // inherited from MultiBodyConstraintSolver
+ solveGroupCacheFriendlySetup(bodies, numBodies, manifold, numManifolds, constraints, numConstraints, info, debugDrawer);
+
+ // overriden
+ solveDeformableGroupIterations(bodies, numBodies, deformableBodies, numDeformableBodies, manifold, numManifolds, constraints, numConstraints, info, debugDrawer);
+
+ // inherited from MultiBodyConstraintSolver
+ solveGroupCacheFriendlyFinish(bodies, numBodies, info);
+
+ m_tmpMultiBodyConstraints = 0;
+ m_tmpNumMultiBodyConstraints = 0;
+}
+
+void btDeformableMultiBodyConstraintSolver::writeToSolverBody(btCollisionObject** bodies, int numBodies, const btContactSolverInfo& infoGlobal)
+{
+ for (int i = 0; i < numBodies; i++)
+ {
+ int bodyId = getOrInitSolverBody(*bodies[i], infoGlobal.m_timeStep);
+
+ btRigidBody* body = btRigidBody::upcast(bodies[i]);
+ if (body && body->getInvMass())
+ {
+ btSolverBody& solverBody = m_tmpSolverBodyPool[bodyId];
+ solverBody.m_linearVelocity = body->getLinearVelocity() - solverBody.m_deltaLinearVelocity;
+ solverBody.m_angularVelocity = body->getAngularVelocity() - solverBody.m_deltaAngularVelocity;
+ }
+ }
+}
+
+void btDeformableMultiBodyConstraintSolver::solverBodyWriteBack(const btContactSolverInfo& infoGlobal)
+{
+ for (int i = 0; i < m_tmpSolverBodyPool.size(); i++)
+ {
+ btRigidBody* body = m_tmpSolverBodyPool[i].m_originalBody;
+ if (body)
+ {
+ m_tmpSolverBodyPool[i].m_originalBody->setLinearVelocity(m_tmpSolverBodyPool[i].m_linearVelocity + m_tmpSolverBodyPool[i].m_deltaLinearVelocity);
+ m_tmpSolverBodyPool[i].m_originalBody->setAngularVelocity(m_tmpSolverBodyPool[i].m_angularVelocity+m_tmpSolverBodyPool[i].m_deltaAngularVelocity);
+ }
+ }
+}
+
+void btDeformableMultiBodyConstraintSolver::solveGroupCacheFriendlySplitImpulseIterations(btCollisionObject** bodies, int numBodies, btPersistentManifold** manifoldPtr, int numManifolds, btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& infoGlobal, btIDebugDraw* debugDrawer)
+{
+ BT_PROFILE("solveGroupCacheFriendlySplitImpulseIterations");
+ int iteration;
+ if (infoGlobal.m_splitImpulse)
+ {
+ {
+ m_deformableSolver->splitImpulseSetup(infoGlobal);
+ for (iteration = 0; iteration < infoGlobal.m_numIterations; iteration++)
+ {
+ btScalar leastSquaresResidual = 0.f;
+ {
+ int numPoolConstraints = m_tmpSolverContactConstraintPool.size();
+ int j;
+ for (j = 0; j < numPoolConstraints; j++)
+ {
+ const btSolverConstraint& solveManifold = m_tmpSolverContactConstraintPool[m_orderTmpConstraintPool[j]];
+
+ btScalar residual = resolveSplitPenetrationImpulse(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA], m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB], solveManifold);
+ leastSquaresResidual = btMax(leastSquaresResidual, residual * residual);
+ }
+ // solve the position correction between deformable and rigid/multibody
+ btScalar residual = m_deformableSolver->solveSplitImpulse(infoGlobal);
+ leastSquaresResidual = btMax(leastSquaresResidual, residual * residual);
+ }
+ if (leastSquaresResidual <= infoGlobal.m_leastSquaresResidualThreshold || iteration >= (infoGlobal.m_numIterations - 1))
+ {
+#ifdef VERBOSE_RESIDUAL_PRINTF
+ printf("residual = %f at iteration #%d\n", leastSquaresResidual, iteration);
+#endif
+ break;
+ }
+ }
+ }
+ }
+}
diff --git a/thirdparty/bullet/BulletSoftBody/btDeformableMultiBodyConstraintSolver.h b/thirdparty/bullet/BulletSoftBody/btDeformableMultiBodyConstraintSolver.h
new file mode 100644
index 0000000000..0c7cc26a83
--- /dev/null
+++ b/thirdparty/bullet/BulletSoftBody/btDeformableMultiBodyConstraintSolver.h
@@ -0,0 +1,61 @@
+/*
+ Written by Xuchen Han <xuchenhan2015@u.northwestern.edu>
+
+ Bullet Continuous Collision Detection and Physics Library
+ Copyright (c) 2019 Google Inc. http://bulletphysics.org
+ 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.
+ */
+
+
+#ifndef BT_DEFORMABLE_MULTIBODY_CONSTRAINT_SOLVER_H
+#define BT_DEFORMABLE_MULTIBODY_CONSTRAINT_SOLVER_H
+
+#include "btDeformableBodySolver.h"
+#include "BulletDynamics/Featherstone/btMultiBodyConstraintSolver.h"
+
+class btDeformableBodySolver;
+
+// btDeformableMultiBodyConstraintSolver extendsn btMultiBodyConstraintSolver to solve for the contact among rigid/multibody and deformable bodies. Notice that the following constraints
+// 1. rigid/multibody against rigid/multibody
+// 2. rigid/multibody against deforamble
+// 3. deformable against deformable
+// 4. deformable self collision
+// 5. joint constraints
+// are all coupled in this solve.
+ATTRIBUTE_ALIGNED16(class)
+btDeformableMultiBodyConstraintSolver : public btMultiBodyConstraintSolver
+{
+ btDeformableBodySolver* m_deformableSolver;
+
+protected:
+ // override the iterations method to include deformable/multibody contact
+// virtual btScalar solveGroupCacheFriendlyIterations(btCollisionObject** bodies,int numBodies,btPersistentManifold** manifoldPtr, int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& infoGlobal,btIDebugDraw* debugDrawer);
+
+ // write the velocity of the the solver body to the underlying rigid body
+ void solverBodyWriteBack(const btContactSolverInfo& infoGlobal);
+
+ // write the velocity of the underlying rigid body to the the the solver body
+ void writeToSolverBody(btCollisionObject** bodies, int numBodies, const btContactSolverInfo& infoGlobal);
+
+ virtual void solveGroupCacheFriendlySplitImpulseIterations(btCollisionObject** bodies, int numBodies, btPersistentManifold** manifoldPtr, int numManifolds, btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& infoGlobal, btIDebugDraw* debugDrawer);
+
+ virtual btScalar solveDeformableGroupIterations(btCollisionObject** bodies,int numBodies,btCollisionObject** deformableBodies,int numDeformableBodies,btPersistentManifold** manifoldPtr, int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& infoGlobal,btIDebugDraw* debugDrawer);
+public:
+ BT_DECLARE_ALIGNED_ALLOCATOR();
+
+ void setDeformableSolver(btDeformableBodySolver* deformableSolver)
+ {
+ m_deformableSolver = deformableSolver;
+ }
+
+ virtual void solveDeformableBodyGroup(btCollisionObject * *bodies, int numBodies, btCollisionObject * *deformableBodies, int numDeformableBodies, btPersistentManifold** manifold, int numManifolds, btTypedConstraint** constraints, int numConstraints, btMultiBodyConstraint** multiBodyConstraints, int numMultiBodyConstraints, const btContactSolverInfo& info, btIDebugDraw* debugDrawer, btDispatcher* dispatcher);
+};
+
+#endif /* BT_DEFORMABLE_MULTIBODY_CONSTRAINT_SOLVER_H */
diff --git a/thirdparty/bullet/BulletSoftBody/btDeformableMultiBodyDynamicsWorld.cpp b/thirdparty/bullet/BulletSoftBody/btDeformableMultiBodyDynamicsWorld.cpp
new file mode 100644
index 0000000000..618e5c0d7b
--- /dev/null
+++ b/thirdparty/bullet/BulletSoftBody/btDeformableMultiBodyDynamicsWorld.cpp
@@ -0,0 +1,653 @@
+/*
+ Written by Xuchen Han <xuchenhan2015@u.northwestern.edu>
+
+ Bullet Continuous Collision Detection and Physics Library
+ Copyright (c) 2019 Google Inc. http://bulletphysics.org
+ 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.
+ */
+
+/* ====== Overview of the Deformable Algorithm ====== */
+
+/*
+A single step of the deformable body simulation contains the following main components:
+Call internalStepSimulation multiple times, to achieve 240Hz (4 steps of 60Hz).
+1. Deformable maintaintenance of rest lengths and volume preservation. Forces only depend on position: Update velocity to a temporary state v_{n+1}^* = v_n + explicit_force * dt / mass, where explicit forces include gravity and elastic forces.
+2. Detect discrete collisions between rigid and deformable bodies at position x_{n+1}^* = x_n + dt * v_{n+1}^*.
+
+3a. Solve all constraints, including LCP. Contact, position correction due to numerical drift, friction, and anchors for deformable.
+ TODO: add option for positional drift correction (using vel_target += erp * pos_error/dt
+
+3b. 5 Newton steps (multiple step). Conjugent Gradient solves linear system. Deformable Damping: Then velocities of deformable bodies v_{n+1} are solved in
+ M(v_{n+1} - v_{n+1}^*) = damping_force * dt / mass,
+ by a conjugate gradient solver, where the damping force is implicit and depends on v_{n+1}.
+ Make sure contact constraints are not violated in step b by performing velocity projections as in the paper by Baraff and Witkin https://www.cs.cmu.edu/~baraff/papers/sig98.pdf. Dynamic frictions are treated as a force and added to the rhs of the CG solve, whereas static frictions are treated as constraints similar to contact.
+4. Position is updated via x_{n+1} = x_n + dt * v_{n+1}.
+
+
+The algorithm also closely resembles the one in http://physbam.stanford.edu/~fedkiw/papers/stanford2008-03.pdf
+ */
+
+#include <stdio.h>
+#include "btDeformableMultiBodyDynamicsWorld.h"
+#include "DeformableBodyInplaceSolverIslandCallback.h"
+#include "btDeformableBodySolver.h"
+#include "LinearMath/btQuickprof.h"
+#include "btSoftBodyInternals.h"
+btDeformableMultiBodyDynamicsWorld::btDeformableMultiBodyDynamicsWorld(btDispatcher* dispatcher, btBroadphaseInterface* pairCache, btDeformableMultiBodyConstraintSolver* constraintSolver, btCollisionConfiguration* collisionConfiguration, btDeformableBodySolver* deformableBodySolver)
+: btMultiBodyDynamicsWorld(dispatcher, pairCache, (btMultiBodyConstraintSolver*)constraintSolver, collisionConfiguration),
+m_deformableBodySolver(deformableBodySolver), m_solverCallback(0)
+{
+ m_drawFlags = fDrawFlags::Std;
+ m_drawNodeTree = true;
+ m_drawFaceTree = false;
+ m_drawClusterTree = false;
+ m_sbi.m_broadphase = pairCache;
+ m_sbi.m_dispatcher = dispatcher;
+ m_sbi.m_sparsesdf.Initialize();
+ m_sbi.m_sparsesdf.setDefaultVoxelsz(0.005);
+ m_sbi.m_sparsesdf.Reset();
+
+ m_sbi.air_density = (btScalar)1.2;
+ m_sbi.water_density = 0;
+ m_sbi.water_offset = 0;
+ m_sbi.water_normal = btVector3(0, 0, 0);
+ m_sbi.m_gravity.setValue(0, -10, 0);
+ m_internalTime = 0.0;
+ m_implicit = false;
+ m_lineSearch = false;
+ m_selfCollision = true;
+ m_solverDeformableBodyIslandCallback = new DeformableBodyInplaceSolverIslandCallback(constraintSolver, dispatcher);
+}
+
+void btDeformableMultiBodyDynamicsWorld::internalSingleStepSimulation(btScalar timeStep)
+{
+ BT_PROFILE("internalSingleStepSimulation");
+ if (0 != m_internalPreTickCallback)
+ {
+ (*m_internalPreTickCallback)(this, timeStep);
+ }
+ reinitialize(timeStep);
+ // add gravity to velocity of rigid and multi bodys
+ applyRigidBodyGravity(timeStep);
+
+ ///apply gravity and explicit force to velocity, predict motion
+ predictUnconstraintMotion(timeStep);
+
+ ///perform collision detection
+ btMultiBodyDynamicsWorld::performDiscreteCollisionDetection();
+
+ if (m_selfCollision)
+ {
+ softBodySelfCollision();
+ }
+
+ btMultiBodyDynamicsWorld::calculateSimulationIslands();
+
+ beforeSolverCallbacks(timeStep);
+
+ ///solve contact constraints and then deformable bodies momemtum equation
+ solveConstraints(timeStep);
+
+ afterSolverCallbacks(timeStep);
+
+ integrateTransforms(timeStep);
+
+ ///update vehicle simulation
+ btMultiBodyDynamicsWorld::updateActions(timeStep);
+
+ updateActivationState(timeStep);
+ // End solver-wise simulation step
+ // ///////////////////////////////
+}
+
+void btDeformableMultiBodyDynamicsWorld::updateActivationState(btScalar timeStep)
+{
+ for (int i = 0; i < m_softBodies.size(); i++)
+ {
+ btSoftBody* psb = m_softBodies[i];
+ psb->updateDeactivation(timeStep);
+ if (psb->wantsSleeping())
+ {
+ if (psb->getActivationState() == ACTIVE_TAG)
+ psb->setActivationState(WANTS_DEACTIVATION);
+ if (psb->getActivationState() == ISLAND_SLEEPING)
+ {
+ psb->setZeroVelocity();
+ }
+ }
+ else
+ {
+ if (psb->getActivationState() != DISABLE_DEACTIVATION)
+ psb->setActivationState(ACTIVE_TAG);
+ }
+ }
+ btMultiBodyDynamicsWorld::updateActivationState(timeStep);
+}
+
+
+void btDeformableMultiBodyDynamicsWorld::softBodySelfCollision()
+{
+ m_deformableBodySolver->updateSoftBodies();
+ for (int i = 0; i < m_softBodies.size(); i++)
+ {
+ btSoftBody* psb = m_softBodies[i];
+ if (psb->isActive())
+ {
+ psb->defaultCollisionHandler(psb);
+ }
+ }
+}
+
+void btDeformableMultiBodyDynamicsWorld::positionCorrection(btScalar timeStep)
+{
+ // correct the position of rigid bodies with temporary velocity generated from split impulse
+ btContactSolverInfo infoGlobal;
+ btVector3 zero(0,0,0);
+ for (int i = 0; i < m_nonStaticRigidBodies.size(); ++i)
+ {
+ btRigidBody* rb = m_nonStaticRigidBodies[i];
+ //correct the position/orientation based on push/turn recovery
+ btTransform newTransform;
+ btVector3 pushVelocity = rb->getPushVelocity();
+ btVector3 turnVelocity = rb->getTurnVelocity();
+ if (pushVelocity[0] != 0.f || pushVelocity[1] != 0 || pushVelocity[2] != 0 || turnVelocity[0] != 0.f || turnVelocity[1] != 0 || turnVelocity[2] != 0)
+ {
+ btTransformUtil::integrateTransform(rb->getWorldTransform(), pushVelocity, turnVelocity * infoGlobal.m_splitImpulseTurnErp, timeStep, newTransform);
+ rb->setWorldTransform(newTransform);
+ rb->setPushVelocity(zero);
+ rb->setTurnVelocity(zero);
+ }
+ }
+}
+
+void btDeformableMultiBodyDynamicsWorld::integrateTransforms(btScalar timeStep)
+{
+ BT_PROFILE("integrateTransforms");
+ positionCorrection(timeStep);
+ btMultiBodyDynamicsWorld::integrateTransforms(timeStep);
+ for (int i = 0; i < m_softBodies.size(); ++i)
+ {
+ btSoftBody* psb = m_softBodies[i];
+ for (int j = 0; j < psb->m_nodes.size(); ++j)
+ {
+ btSoftBody::Node& node = psb->m_nodes[j];
+ btScalar maxDisplacement = psb->getWorldInfo()->m_maxDisplacement;
+ btScalar clampDeltaV = maxDisplacement / timeStep;
+ for (int c = 0; c < 3; c++)
+ {
+ if (node.m_v[c] > clampDeltaV)
+ {
+ node.m_v[c] = clampDeltaV;
+ }
+ if (node.m_v[c] < -clampDeltaV)
+ {
+ node.m_v[c] = -clampDeltaV;
+ }
+ }
+ node.m_x = node.m_x + timeStep * node.m_v;
+ node.m_v -= node.m_vsplit;
+ node.m_vsplit.setZero();
+ node.m_q = node.m_x;
+ node.m_vn = node.m_v;
+ }
+ // enforce anchor constraints
+ for (int j = 0; j < psb->m_deformableAnchors.size();++j)
+ {
+ btSoftBody::DeformableNodeRigidAnchor& a = psb->m_deformableAnchors[j];
+ btSoftBody::Node* n = a.m_node;
+ n->m_x = a.m_cti.m_colObj->getWorldTransform() * a.m_local;
+
+ // update multibody anchor info
+ if (a.m_cti.m_colObj->getInternalType() == btCollisionObject::CO_FEATHERSTONE_LINK)
+ {
+ btMultiBodyLinkCollider* multibodyLinkCol = (btMultiBodyLinkCollider*)btMultiBodyLinkCollider::upcast(a.m_cti.m_colObj);
+ if (multibodyLinkCol)
+ {
+ btVector3 nrm;
+ const btCollisionShape* shp = multibodyLinkCol->getCollisionShape();
+ const btTransform& wtr = multibodyLinkCol->getWorldTransform();
+ psb->m_worldInfo->m_sparsesdf.Evaluate(
+ wtr.invXform(n->m_x),
+ shp,
+ nrm,
+ 0);
+ a.m_cti.m_normal = wtr.getBasis() * nrm;
+ btVector3 normal = a.m_cti.m_normal;
+ btVector3 t1 = generateUnitOrthogonalVector(normal);
+ btVector3 t2 = btCross(normal, t1);
+ btMultiBodyJacobianData jacobianData_normal, jacobianData_t1, jacobianData_t2;
+ findJacobian(multibodyLinkCol, jacobianData_normal, a.m_node->m_x, normal);
+ findJacobian(multibodyLinkCol, jacobianData_t1, a.m_node->m_x, t1);
+ findJacobian(multibodyLinkCol, jacobianData_t2, a.m_node->m_x, t2);
+
+ btScalar* J_n = &jacobianData_normal.m_jacobians[0];
+ btScalar* J_t1 = &jacobianData_t1.m_jacobians[0];
+ btScalar* J_t2 = &jacobianData_t2.m_jacobians[0];
+
+ btScalar* u_n = &jacobianData_normal.m_deltaVelocitiesUnitImpulse[0];
+ btScalar* u_t1 = &jacobianData_t1.m_deltaVelocitiesUnitImpulse[0];
+ btScalar* u_t2 = &jacobianData_t2.m_deltaVelocitiesUnitImpulse[0];
+
+ btMatrix3x3 rot(normal.getX(), normal.getY(), normal.getZ(),
+ t1.getX(), t1.getY(), t1.getZ(),
+ t2.getX(), t2.getY(), t2.getZ()); // world frame to local frame
+ const int ndof = multibodyLinkCol->m_multiBody->getNumDofs() + 6;
+ btMatrix3x3 local_impulse_matrix = (Diagonal(n->m_im) + OuterProduct(J_n, J_t1, J_t2, u_n, u_t1, u_t2, ndof)).inverse();
+ a.m_c0 = rot.transpose() * local_impulse_matrix * rot;
+ a.jacobianData_normal = jacobianData_normal;
+ a.jacobianData_t1 = jacobianData_t1;
+ a.jacobianData_t2 = jacobianData_t2;
+ a.t1 = t1;
+ a.t2 = t2;
+ }
+ }
+ }
+ psb->interpolateRenderMesh();
+ }
+}
+
+void btDeformableMultiBodyDynamicsWorld::solveConstraints(btScalar timeStep)
+{
+ // save v_{n+1}^* velocity after explicit forces
+ m_deformableBodySolver->backupVelocity();
+
+ // set up constraints among multibodies and between multibodies and deformable bodies
+ setupConstraints();
+
+ // solve contact constraints
+ solveContactConstraints();
+
+ // set up the directions in which the velocity does not change in the momentum solve
+ m_deformableBodySolver->m_objective->m_projection.setProjection();
+
+ // for explicit scheme, m_backupVelocity = v_{n+1}^*
+ // for implicit scheme, m_backupVelocity = v_n
+ // Here, set dv = v_{n+1} - v_n for nodes in contact
+ m_deformableBodySolver->setupDeformableSolve(m_implicit);
+
+ // At this point, dv should be golden for nodes in contact
+ // proceed to solve deformable momentum equation
+ m_deformableBodySolver->solveDeformableConstraints(timeStep);
+}
+
+void btDeformableMultiBodyDynamicsWorld::setupConstraints()
+{
+ // set up constraints between multibody and deformable bodies
+ m_deformableBodySolver->setConstraints();
+
+ // set up constraints among multibodies
+ {
+ sortConstraints();
+ // setup the solver callback
+ btMultiBodyConstraint** sortedMultiBodyConstraints = m_sortedMultiBodyConstraints.size() ? &m_sortedMultiBodyConstraints[0] : 0;
+ btTypedConstraint** constraintsPtr = getNumConstraints() ? &m_sortedConstraints[0] : 0;
+ m_solverDeformableBodyIslandCallback->setup(&m_solverInfo, constraintsPtr, m_sortedConstraints.size(), sortedMultiBodyConstraints, m_sortedMultiBodyConstraints.size(), getDebugDrawer());
+
+ // build islands
+ m_islandManager->buildIslands(getCollisionWorld()->getDispatcher(), getCollisionWorld());
+ }
+}
+
+void btDeformableMultiBodyDynamicsWorld::sortConstraints()
+{
+ m_sortedConstraints.resize(m_constraints.size());
+ int i;
+ for (i = 0; i < getNumConstraints(); i++)
+ {
+ m_sortedConstraints[i] = m_constraints[i];
+ }
+ m_sortedConstraints.quickSort(btSortConstraintOnIslandPredicate2());
+
+ m_sortedMultiBodyConstraints.resize(m_multiBodyConstraints.size());
+ for (i = 0; i < m_multiBodyConstraints.size(); i++)
+ {
+ m_sortedMultiBodyConstraints[i] = m_multiBodyConstraints[i];
+ }
+ m_sortedMultiBodyConstraints.quickSort(btSortMultiBodyConstraintOnIslandPredicate());
+}
+
+
+void btDeformableMultiBodyDynamicsWorld::solveContactConstraints()
+{
+ // process constraints on each island
+ m_islandManager->processIslands(getCollisionWorld()->getDispatcher(), getCollisionWorld(), m_solverDeformableBodyIslandCallback);
+
+ // process deferred
+ m_solverDeformableBodyIslandCallback->processConstraints();
+ m_constraintSolver->allSolved(m_solverInfo, m_debugDrawer);
+
+ // write joint feedback
+ {
+ for (int i = 0; i < this->m_multiBodies.size(); i++)
+ {
+ btMultiBody* bod = m_multiBodies[i];
+
+ bool isSleeping = false;
+
+ if (bod->getBaseCollider() && bod->getBaseCollider()->getActivationState() == ISLAND_SLEEPING)
+ {
+ isSleeping = true;
+ }
+ for (int b = 0; b < bod->getNumLinks(); b++)
+ {
+ if (bod->getLink(b).m_collider && bod->getLink(b).m_collider->getActivationState() == ISLAND_SLEEPING)
+ isSleeping = true;
+ }
+
+ if (!isSleeping)
+ {
+ //useless? they get resized in stepVelocities once again (AND DIFFERENTLY)
+ m_scratch_r.resize(bod->getNumLinks() + 1); //multidof? ("Y"s use it and it is used to store qdd)
+ m_scratch_v.resize(bod->getNumLinks() + 1);
+ m_scratch_m.resize(bod->getNumLinks() + 1);
+
+ if (bod->internalNeedsJointFeedback())
+ {
+ if (!bod->isUsingRK4Integration())
+ {
+ if (bod->internalNeedsJointFeedback())
+ {
+ bool isConstraintPass = true;
+ bod->computeAccelerationsArticulatedBodyAlgorithmMultiDof(m_solverInfo.m_timeStep, m_scratch_r, m_scratch_v, m_scratch_m, isConstraintPass,
+ getSolverInfo().m_jointFeedbackInWorldSpace,
+ getSolverInfo().m_jointFeedbackInJointFrame);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ for (int i = 0; i < this->m_multiBodies.size(); i++)
+ {
+ btMultiBody* bod = m_multiBodies[i];
+ bod->processDeltaVeeMultiDof2();
+ }
+}
+
+void btDeformableMultiBodyDynamicsWorld::addSoftBody(btSoftBody* body, int collisionFilterGroup, int collisionFilterMask)
+{
+ m_softBodies.push_back(body);
+
+ // Set the soft body solver that will deal with this body
+ // to be the world's solver
+ body->setSoftBodySolver(m_deformableBodySolver);
+
+ btCollisionWorld::addCollisionObject(body,
+ collisionFilterGroup,
+ collisionFilterMask);
+}
+
+void btDeformableMultiBodyDynamicsWorld::predictUnconstraintMotion(btScalar timeStep)
+{
+ BT_PROFILE("predictUnconstraintMotion");
+ btMultiBodyDynamicsWorld::predictUnconstraintMotion(timeStep);
+ m_deformableBodySolver->predictMotion(timeStep);
+}
+
+void btDeformableMultiBodyDynamicsWorld::reinitialize(btScalar timeStep)
+{
+ m_internalTime += timeStep;
+ m_deformableBodySolver->setImplicit(m_implicit);
+ m_deformableBodySolver->setLineSearch(m_lineSearch);
+ m_deformableBodySolver->reinitialize(m_softBodies, timeStep);
+ btDispatcherInfo& dispatchInfo = btMultiBodyDynamicsWorld::getDispatchInfo();
+ dispatchInfo.m_timeStep = timeStep;
+ dispatchInfo.m_stepCount = 0;
+ dispatchInfo.m_debugDraw = btMultiBodyDynamicsWorld::getDebugDrawer();
+ btMultiBodyDynamicsWorld::getSolverInfo().m_timeStep = timeStep;
+}
+
+
+void btDeformableMultiBodyDynamicsWorld::debugDrawWorld()
+{
+
+ btMultiBodyDynamicsWorld::debugDrawWorld();
+
+ for (int i = 0; i < getSoftBodyArray().size(); i++)
+ {
+ btSoftBody* psb = (btSoftBody*)getSoftBodyArray()[i];
+ {
+ btSoftBodyHelpers::DrawFrame(psb, getDebugDrawer());
+ btSoftBodyHelpers::Draw(psb, getDebugDrawer(), getDrawFlags());
+ }
+ }
+
+
+}
+
+void btDeformableMultiBodyDynamicsWorld::applyRigidBodyGravity(btScalar timeStep)
+{
+ // Gravity is applied in stepSimulation and then cleared here and then applied here and then cleared here again
+ // so that 1) gravity is applied to velocity before constraint solve and 2) gravity is applied in each substep
+ // when there are multiple substeps
+ btMultiBodyDynamicsWorld::applyGravity();
+ // integrate rigid body gravity
+ for (int i = 0; i < m_nonStaticRigidBodies.size(); ++i)
+ {
+ btRigidBody* rb = m_nonStaticRigidBodies[i];
+ rb->integrateVelocities(timeStep);
+ }
+
+ // integrate multibody gravity
+ {
+ forwardKinematics();
+ clearMultiBodyConstraintForces();
+ {
+ for (int i = 0; i < this->m_multiBodies.size(); i++)
+ {
+ btMultiBody* bod = m_multiBodies[i];
+
+ bool isSleeping = false;
+
+ if (bod->getBaseCollider() && bod->getBaseCollider()->getActivationState() == ISLAND_SLEEPING)
+ {
+ isSleeping = true;
+ }
+ for (int b = 0; b < bod->getNumLinks(); b++)
+ {
+ if (bod->getLink(b).m_collider && bod->getLink(b).m_collider->getActivationState() == ISLAND_SLEEPING)
+ isSleeping = true;
+ }
+
+ if (!isSleeping)
+ {
+ m_scratch_r.resize(bod->getNumLinks() + 1);
+ m_scratch_v.resize(bod->getNumLinks() + 1);
+ m_scratch_m.resize(bod->getNumLinks() + 1);
+ bool isConstraintPass = false;
+ {
+ if (!bod->isUsingRK4Integration())
+ {
+ bod->computeAccelerationsArticulatedBodyAlgorithmMultiDof(m_solverInfo.m_timeStep,
+ m_scratch_r, m_scratch_v, m_scratch_m,isConstraintPass,
+ getSolverInfo().m_jointFeedbackInWorldSpace,
+ getSolverInfo().m_jointFeedbackInJointFrame);
+ }
+ else
+ {
+ btAssert(" RK4Integration is not supported" );
+ }
+ }
+ }
+ }
+ }
+ }
+ clearGravity();
+}
+
+void btDeformableMultiBodyDynamicsWorld::clearGravity()
+{
+ BT_PROFILE("btMultiBody clearGravity");
+ // clear rigid body gravity
+ for (int i = 0; i < m_nonStaticRigidBodies.size(); i++)
+ {
+ btRigidBody* body = m_nonStaticRigidBodies[i];
+ if (body->isActive())
+ {
+ body->clearGravity();
+ }
+ }
+ // clear multibody gravity
+ for (int i = 0; i < this->m_multiBodies.size(); i++)
+ {
+ btMultiBody* bod = m_multiBodies[i];
+
+ bool isSleeping = false;
+
+ if (bod->getBaseCollider() && bod->getBaseCollider()->getActivationState() == ISLAND_SLEEPING)
+ {
+ isSleeping = true;
+ }
+ for (int b = 0; b < bod->getNumLinks(); b++)
+ {
+ if (bod->getLink(b).m_collider && bod->getLink(b).m_collider->getActivationState() == ISLAND_SLEEPING)
+ isSleeping = true;
+ }
+
+ if (!isSleeping)
+ {
+ bod->addBaseForce(-m_gravity * bod->getBaseMass());
+
+ for (int j = 0; j < bod->getNumLinks(); ++j)
+ {
+ bod->addLinkForce(j, -m_gravity * bod->getLinkMass(j));
+ }
+ }
+ }
+}
+
+void btDeformableMultiBodyDynamicsWorld::beforeSolverCallbacks(btScalar timeStep)
+{
+ if (0 != m_internalTickCallback)
+ {
+ (*m_internalTickCallback)(this, timeStep);
+ }
+
+ if (0 != m_solverCallback)
+ {
+ (*m_solverCallback)(m_internalTime, this);
+ }
+}
+
+void btDeformableMultiBodyDynamicsWorld::afterSolverCallbacks(btScalar timeStep)
+{
+ if (0 != m_solverCallback)
+ {
+ (*m_solverCallback)(m_internalTime, this);
+ }
+}
+
+void btDeformableMultiBodyDynamicsWorld::addForce(btSoftBody* psb, btDeformableLagrangianForce* force)
+{
+ btAlignedObjectArray<btDeformableLagrangianForce*>& forces = m_deformableBodySolver->m_objective->m_lf;
+ bool added = false;
+ for (int i = 0; i < forces.size(); ++i)
+ {
+ if (forces[i]->getForceType() == force->getForceType())
+ {
+ forces[i]->addSoftBody(psb);
+ added = true;
+ break;
+ }
+ }
+ if (!added)
+ {
+ force->addSoftBody(psb);
+ force->setIndices(m_deformableBodySolver->m_objective->getIndices());
+ forces.push_back(force);
+ }
+}
+
+void btDeformableMultiBodyDynamicsWorld::removeSoftBody(btSoftBody* body)
+{
+ m_softBodies.remove(body);
+ btCollisionWorld::removeCollisionObject(body);
+ // force a reinitialize so that node indices get updated.
+ m_deformableBodySolver->reinitialize(m_softBodies, btScalar(-1));
+}
+
+void btDeformableMultiBodyDynamicsWorld::removeCollisionObject(btCollisionObject* collisionObject)
+{
+ btSoftBody* body = btSoftBody::upcast(collisionObject);
+ if (body)
+ removeSoftBody(body);
+ else
+ btDiscreteDynamicsWorld::removeCollisionObject(collisionObject);
+}
+
+
+int btDeformableMultiBodyDynamicsWorld::stepSimulation(btScalar timeStep, int maxSubSteps, btScalar fixedTimeStep)
+{
+ startProfiling(timeStep);
+
+ int numSimulationSubSteps = 0;
+
+ if (maxSubSteps)
+ {
+ //fixed timestep with interpolation
+ m_fixedTimeStep = fixedTimeStep;
+ m_localTime += timeStep;
+ if (m_localTime >= fixedTimeStep)
+ {
+ numSimulationSubSteps = int(m_localTime / fixedTimeStep);
+ m_localTime -= numSimulationSubSteps * fixedTimeStep;
+ }
+ }
+ else
+ {
+ //variable timestep
+ fixedTimeStep = timeStep;
+ m_localTime = m_latencyMotionStateInterpolation ? 0 : timeStep;
+ m_fixedTimeStep = 0;
+ if (btFuzzyZero(timeStep))
+ {
+ numSimulationSubSteps = 0;
+ maxSubSteps = 0;
+ }
+ else
+ {
+ numSimulationSubSteps = 1;
+ maxSubSteps = 1;
+ }
+ }
+
+ //process some debugging flags
+ if (getDebugDrawer())
+ {
+ btIDebugDraw* debugDrawer = getDebugDrawer();
+ gDisableDeactivation = (debugDrawer->getDebugMode() & btIDebugDraw::DBG_NoDeactivation) != 0;
+ }
+ if (numSimulationSubSteps)
+ {
+ //clamp the number of substeps, to prevent simulation grinding spiralling down to a halt
+ int clampedSimulationSteps = (numSimulationSubSteps > maxSubSteps) ? maxSubSteps : numSimulationSubSteps;
+
+ saveKinematicState(fixedTimeStep * clampedSimulationSteps);
+
+ for (int i = 0; i < clampedSimulationSteps; i++)
+ {
+ internalSingleStepSimulation(fixedTimeStep);
+ synchronizeMotionStates();
+ }
+ }
+ else
+ {
+ synchronizeMotionStates();
+ }
+
+ clearForces();
+
+#ifndef BT_NO_PROFILE
+ CProfileManager::Increment_Frame_Counter();
+#endif //BT_NO_PROFILE
+
+ return numSimulationSubSteps;
+}
diff --git a/thirdparty/bullet/BulletSoftBody/btDeformableMultiBodyDynamicsWorld.h b/thirdparty/bullet/BulletSoftBody/btDeformableMultiBodyDynamicsWorld.h
new file mode 100644
index 0000000000..7630385767
--- /dev/null
+++ b/thirdparty/bullet/BulletSoftBody/btDeformableMultiBodyDynamicsWorld.h
@@ -0,0 +1,165 @@
+/*
+ Written by Xuchen Han <xuchenhan2015@u.northwestern.edu>
+
+ Bullet Continuous Collision Detection and Physics Library
+ Copyright (c) 2019 Google Inc. http://bulletphysics.org
+ 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.
+ */
+
+#ifndef BT_DEFORMABLE_MULTIBODY_DYNAMICS_WORLD_H
+#define BT_DEFORMABLE_MULTIBODY_DYNAMICS_WORLD_H
+
+#include "btSoftMultiBodyDynamicsWorld.h"
+#include "btDeformableLagrangianForce.h"
+#include "btDeformableMassSpringForce.h"
+#include "btDeformableBodySolver.h"
+#include "btDeformableMultiBodyConstraintSolver.h"
+#include "btSoftBodyHelpers.h"
+#include "BulletCollision/CollisionDispatch/btSimulationIslandManager.h"
+#include <functional>
+typedef btAlignedObjectArray<btSoftBody*> btSoftBodyArray;
+
+class btDeformableBodySolver;
+class btDeformableLagrangianForce;
+struct MultiBodyInplaceSolverIslandCallback;
+struct DeformableBodyInplaceSolverIslandCallback;
+class btDeformableMultiBodyConstraintSolver;
+
+typedef btAlignedObjectArray<btSoftBody*> btSoftBodyArray;
+
+class btDeformableMultiBodyDynamicsWorld : public btMultiBodyDynamicsWorld
+{
+ typedef btAlignedObjectArray<btVector3> TVStack;
+ ///Solver classes that encapsulate multiple deformable bodies for solving
+ btDeformableBodySolver* m_deformableBodySolver;
+ btSoftBodyArray m_softBodies;
+ int m_drawFlags;
+ bool m_drawNodeTree;
+ bool m_drawFaceTree;
+ bool m_drawClusterTree;
+ btSoftBodyWorldInfo m_sbi;
+ btScalar m_internalTime;
+ int m_contact_iterations;
+ bool m_implicit;
+ bool m_lineSearch;
+ bool m_selfCollision;
+ DeformableBodyInplaceSolverIslandCallback* m_solverDeformableBodyIslandCallback;
+
+ typedef void (*btSolverCallback)(btScalar time, btDeformableMultiBodyDynamicsWorld* world);
+ btSolverCallback m_solverCallback;
+
+protected:
+ virtual void internalSingleStepSimulation(btScalar timeStep);
+
+ virtual void integrateTransforms(btScalar timeStep);
+
+ void positionCorrection(btScalar timeStep);
+
+ void solveConstraints(btScalar timeStep);
+
+ void updateActivationState(btScalar timeStep);
+
+ void clearGravity();
+
+public:
+ btDeformableMultiBodyDynamicsWorld(btDispatcher* dispatcher, btBroadphaseInterface* pairCache, btDeformableMultiBodyConstraintSolver* constraintSolver, btCollisionConfiguration* collisionConfiguration, btDeformableBodySolver* deformableBodySolver = 0);
+
+ virtual int stepSimulation(btScalar timeStep, int maxSubSteps = 1, btScalar fixedTimeStep = btScalar(1.) / btScalar(60.));
+
+ virtual void debugDrawWorld();
+
+ void setSolverCallback(btSolverCallback cb)
+ {
+ m_solverCallback = cb;
+ }
+
+ virtual ~btDeformableMultiBodyDynamicsWorld()
+ {
+ }
+
+ virtual btMultiBodyDynamicsWorld* getMultiBodyDynamicsWorld()
+ {
+ return (btMultiBodyDynamicsWorld*)(this);
+ }
+
+ virtual const btMultiBodyDynamicsWorld* getMultiBodyDynamicsWorld() const
+ {
+ return (const btMultiBodyDynamicsWorld*)(this);
+ }
+
+ virtual btDynamicsWorldType getWorldType() const
+ {
+ return BT_DEFORMABLE_MULTIBODY_DYNAMICS_WORLD;
+ }
+
+ virtual void predictUnconstraintMotion(btScalar timeStep);
+
+ virtual void addSoftBody(btSoftBody* body, int collisionFilterGroup = btBroadphaseProxy::DefaultFilter, int collisionFilterMask = btBroadphaseProxy::AllFilter);
+
+ btSoftBodyArray& getSoftBodyArray()
+ {
+ return m_softBodies;
+ }
+
+ const btSoftBodyArray& getSoftBodyArray() const
+ {
+ return m_softBodies;
+ }
+
+ btSoftBodyWorldInfo& getWorldInfo()
+ {
+ return m_sbi;
+ }
+
+ const btSoftBodyWorldInfo& getWorldInfo() const
+ {
+ return m_sbi;
+ }
+
+ void reinitialize(btScalar timeStep);
+
+ void applyRigidBodyGravity(btScalar timeStep);
+
+ void beforeSolverCallbacks(btScalar timeStep);
+
+ void afterSolverCallbacks(btScalar timeStep);
+
+ void addForce(btSoftBody* psb, btDeformableLagrangianForce* force);
+
+ void removeSoftBody(btSoftBody* body);
+
+ void removeCollisionObject(btCollisionObject* collisionObject);
+
+ int getDrawFlags() const { return (m_drawFlags); }
+ void setDrawFlags(int f) { m_drawFlags = f; }
+
+ void setupConstraints();
+
+ void solveMultiBodyConstraints();
+
+ void solveContactConstraints();
+
+ void sortConstraints();
+
+ void softBodySelfCollision();
+
+ void setImplicit(bool implicit)
+ {
+ m_implicit = implicit;
+ }
+
+ void setLineSearch(bool lineSearch)
+ {
+ m_lineSearch = lineSearch;
+ }
+
+};
+
+#endif //BT_DEFORMABLE_MULTIBODY_DYNAMICS_WORLD_H
diff --git a/thirdparty/bullet/BulletSoftBody/btDeformableNeoHookeanForce.h b/thirdparty/bullet/BulletSoftBody/btDeformableNeoHookeanForce.h
new file mode 100644
index 0000000000..3d06e304d2
--- /dev/null
+++ b/thirdparty/bullet/BulletSoftBody/btDeformableNeoHookeanForce.h
@@ -0,0 +1,375 @@
+/*
+Written by Xuchen Han <xuchenhan2015@u.northwestern.edu>
+
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2019 Google Inc. http://bulletphysics.org
+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.
+*/
+
+#ifndef BT_NEOHOOKEAN_H
+#define BT_NEOHOOKEAN_H
+
+#include "btDeformableLagrangianForce.h"
+#include "LinearMath/btQuickprof.h"
+#include "LinearMath/btImplicitQRSVD.h"
+// This energy is as described in https://graphics.pixar.com/library/StableElasticity/paper.pdf
+class btDeformableNeoHookeanForce : public btDeformableLagrangianForce
+{
+public:
+ typedef btAlignedObjectArray<btVector3> TVStack;
+ btScalar m_mu, m_lambda;
+ btScalar m_mu_damp, m_lambda_damp;
+ btDeformableNeoHookeanForce(): m_mu(1), m_lambda(1)
+ {
+ btScalar damping = 0.05;
+ m_mu_damp = damping * m_mu;
+ m_lambda_damp = damping * m_lambda;
+ }
+
+ btDeformableNeoHookeanForce(btScalar mu, btScalar lambda, btScalar damping = 0.05): m_mu(mu), m_lambda(lambda)
+ {
+ m_mu_damp = damping * m_mu;
+ m_lambda_damp = damping * m_lambda;
+ }
+
+ virtual void addScaledForces(btScalar scale, TVStack& force)
+ {
+ addScaledDampingForce(scale, force);
+ addScaledElasticForce(scale, force);
+ }
+
+ virtual void addScaledExplicitForce(btScalar scale, TVStack& force)
+ {
+ addScaledElasticForce(scale, force);
+ }
+
+ // The damping matrix is calculated using the time n state as described in https://www.math.ucla.edu/~jteran/papers/GSSJT15.pdf to allow line search
+ virtual void addScaledDampingForce(btScalar scale, TVStack& force)
+ {
+ if (m_mu_damp == 0 && m_lambda_damp == 0)
+ return;
+ int numNodes = getNumNodes();
+ btAssert(numNodes <= force.size());
+ btVector3 grad_N_hat_1st_col = btVector3(-1,-1,-1);
+ for (int i = 0; i < m_softBodies.size(); ++i)
+ {
+ btSoftBody* psb = m_softBodies[i];
+ if (!psb->isActive())
+ {
+ continue;
+ }
+ for (int j = 0; j < psb->m_tetras.size(); ++j)
+ {
+ btSoftBody::Tetra& tetra = psb->m_tetras[j];
+ btSoftBody::Node* node0 = tetra.m_n[0];
+ btSoftBody::Node* node1 = tetra.m_n[1];
+ btSoftBody::Node* node2 = tetra.m_n[2];
+ btSoftBody::Node* node3 = tetra.m_n[3];
+ size_t id0 = node0->index;
+ size_t id1 = node1->index;
+ size_t id2 = node2->index;
+ size_t id3 = node3->index;
+ btMatrix3x3 dF = DsFromVelocity(node0, node1, node2, node3) * tetra.m_Dm_inverse;
+ btMatrix3x3 I;
+ I.setIdentity();
+ btMatrix3x3 dP = (dF + dF.transpose()) * m_mu_damp + I * (dF[0][0]+dF[1][1]+dF[2][2]) * m_lambda_damp;
+// firstPiolaDampingDifferential(psb->m_tetraScratchesTn[j], dF, dP);
+ btVector3 df_on_node0 = dP * (tetra.m_Dm_inverse.transpose()*grad_N_hat_1st_col);
+ btMatrix3x3 df_on_node123 = dP * tetra.m_Dm_inverse.transpose();
+
+ // damping force differential
+ btScalar scale1 = scale * tetra.m_element_measure;
+ force[id0] -= scale1 * df_on_node0;
+ force[id1] -= scale1 * df_on_node123.getColumn(0);
+ force[id2] -= scale1 * df_on_node123.getColumn(1);
+ force[id3] -= scale1 * df_on_node123.getColumn(2);
+ }
+ }
+ }
+
+ virtual double totalElasticEnergy(btScalar dt)
+ {
+ double energy = 0;
+ for (int i = 0; i < m_softBodies.size(); ++i)
+ {
+ btSoftBody* psb = m_softBodies[i];
+ if (!psb->isActive())
+ {
+ continue;
+ }
+ for (int j = 0; j < psb->m_tetraScratches.size(); ++j)
+ {
+ btSoftBody::Tetra& tetra = psb->m_tetras[j];
+ btSoftBody::TetraScratch& s = psb->m_tetraScratches[j];
+ energy += tetra.m_element_measure * elasticEnergyDensity(s);
+ }
+ }
+ return energy;
+ }
+
+ // The damping energy is formulated as in https://www.math.ucla.edu/~jteran/papers/GSSJT15.pdf to allow line search
+ virtual double totalDampingEnergy(btScalar dt)
+ {
+ double energy = 0;
+ int sz = 0;
+ for (int i = 0; i < m_softBodies.size(); ++i)
+ {
+ btSoftBody* psb = m_softBodies[i];
+ if (!psb->isActive())
+ {
+ continue;
+ }
+ for (int j = 0; j < psb->m_nodes.size(); ++j)
+ {
+ sz = btMax(sz, psb->m_nodes[j].index);
+ }
+ }
+ TVStack dampingForce;
+ dampingForce.resize(sz+1);
+ for (int i = 0; i < dampingForce.size(); ++i)
+ dampingForce[i].setZero();
+ addScaledDampingForce(0.5, dampingForce);
+ for (int i = 0; i < m_softBodies.size(); ++i)
+ {
+ btSoftBody* psb = m_softBodies[i];
+ for (int j = 0; j < psb->m_nodes.size(); ++j)
+ {
+ const btSoftBody::Node& node = psb->m_nodes[j];
+ energy -= dampingForce[node.index].dot(node.m_v) / dt;
+ }
+ }
+ return energy;
+ }
+
+ double elasticEnergyDensity(const btSoftBody::TetraScratch& s)
+ {
+ double density = 0;
+ density += m_mu * 0.5 * (s.m_trace - 3.);
+ density += m_lambda * 0.5 * (s.m_J - 1. - 0.75 * m_mu / m_lambda)* (s.m_J - 1. - 0.75 * m_mu / m_lambda);
+ density -= m_mu * 0.5 * log(s.m_trace+1);
+ return density;
+ }
+
+ virtual void addScaledElasticForce(btScalar scale, TVStack& force)
+ {
+ int numNodes = getNumNodes();
+ btAssert(numNodes <= force.size());
+ btVector3 grad_N_hat_1st_col = btVector3(-1,-1,-1);
+ for (int i = 0; i < m_softBodies.size(); ++i)
+ {
+ btSoftBody* psb = m_softBodies[i];
+ if (!psb->isActive())
+ {
+ continue;
+ }
+ btScalar max_p = psb->m_cfg.m_maxStress;
+ for (int j = 0; j < psb->m_tetras.size(); ++j)
+ {
+ btSoftBody::Tetra& tetra = psb->m_tetras[j];
+ btMatrix3x3 P;
+ firstPiola(psb->m_tetraScratches[j],P);
+#ifdef USE_SVD
+ if (max_p > 0)
+ {
+ // since we want to clamp the principal stress to max_p, we only need to
+ // calculate SVD when sigma_0^2 + sigma_1^2 + sigma_2^2 > max_p * max_p
+ btScalar trPTP = (P[0].length2() + P[1].length2() + P[2].length2());
+ if (trPTP > max_p * max_p)
+ {
+ btMatrix3x3 U, V;
+ btVector3 sigma;
+ singularValueDecomposition(P, U, sigma, V);
+ sigma[0] = btMin(sigma[0], max_p);
+ sigma[1] = btMin(sigma[1], max_p);
+ sigma[2] = btMin(sigma[2], max_p);
+ sigma[0] = btMax(sigma[0], -max_p);
+ sigma[1] = btMax(sigma[1], -max_p);
+ sigma[2] = btMax(sigma[2], -max_p);
+ btMatrix3x3 Sigma;
+ Sigma.setIdentity();
+ Sigma[0][0] = sigma[0];
+ Sigma[1][1] = sigma[1];
+ Sigma[2][2] = sigma[2];
+ P = U * Sigma * V.transpose();
+ }
+ }
+#endif
+// btVector3 force_on_node0 = P * (tetra.m_Dm_inverse.transpose()*grad_N_hat_1st_col);
+ btMatrix3x3 force_on_node123 = P * tetra.m_Dm_inverse.transpose();
+ btVector3 force_on_node0 = force_on_node123 * grad_N_hat_1st_col;
+
+ btSoftBody::Node* node0 = tetra.m_n[0];
+ btSoftBody::Node* node1 = tetra.m_n[1];
+ btSoftBody::Node* node2 = tetra.m_n[2];
+ btSoftBody::Node* node3 = tetra.m_n[3];
+ size_t id0 = node0->index;
+ size_t id1 = node1->index;
+ size_t id2 = node2->index;
+ size_t id3 = node3->index;
+
+ // elastic force
+ btScalar scale1 = scale * tetra.m_element_measure;
+ force[id0] -= scale1 * force_on_node0;
+ force[id1] -= scale1 * force_on_node123.getColumn(0);
+ force[id2] -= scale1 * force_on_node123.getColumn(1);
+ force[id3] -= scale1 * force_on_node123.getColumn(2);
+ }
+ }
+ }
+
+ // The damping matrix is calculated using the time n state as described in https://www.math.ucla.edu/~jteran/papers/GSSJT15.pdf to allow line search
+ virtual void addScaledDampingForceDifferential(btScalar scale, const TVStack& dv, TVStack& df)
+ {
+ if (m_mu_damp == 0 && m_lambda_damp == 0)
+ return;
+ int numNodes = getNumNodes();
+ btAssert(numNodes <= df.size());
+ btVector3 grad_N_hat_1st_col = btVector3(-1,-1,-1);
+ for (int i = 0; i < m_softBodies.size(); ++i)
+ {
+ btSoftBody* psb = m_softBodies[i];
+ if (!psb->isActive())
+ {
+ continue;
+ }
+ for (int j = 0; j < psb->m_tetras.size(); ++j)
+ {
+ btSoftBody::Tetra& tetra = psb->m_tetras[j];
+ btSoftBody::Node* node0 = tetra.m_n[0];
+ btSoftBody::Node* node1 = tetra.m_n[1];
+ btSoftBody::Node* node2 = tetra.m_n[2];
+ btSoftBody::Node* node3 = tetra.m_n[3];
+ size_t id0 = node0->index;
+ size_t id1 = node1->index;
+ size_t id2 = node2->index;
+ size_t id3 = node3->index;
+ btMatrix3x3 dF = Ds(id0, id1, id2, id3, dv) * tetra.m_Dm_inverse;
+ btMatrix3x3 I;
+ I.setIdentity();
+ btMatrix3x3 dP = (dF + dF.transpose()) * m_mu_damp + I * (dF[0][0]+dF[1][1]+dF[2][2]) * m_lambda_damp;
+// firstPiolaDampingDifferential(psb->m_tetraScratchesTn[j], dF, dP);
+// btVector3 df_on_node0 = dP * (tetra.m_Dm_inverse.transpose()*grad_N_hat_1st_col);
+ btMatrix3x3 df_on_node123 = dP * tetra.m_Dm_inverse.transpose();
+ btVector3 df_on_node0 = df_on_node123 * grad_N_hat_1st_col;
+
+ // damping force differential
+ btScalar scale1 = scale * tetra.m_element_measure;
+ df[id0] -= scale1 * df_on_node0;
+ df[id1] -= scale1 * df_on_node123.getColumn(0);
+ df[id2] -= scale1 * df_on_node123.getColumn(1);
+ df[id3] -= scale1 * df_on_node123.getColumn(2);
+ }
+ }
+ }
+
+ virtual void addScaledElasticForceDifferential(btScalar scale, const TVStack& dx, TVStack& df)
+ {
+ int numNodes = getNumNodes();
+ btAssert(numNodes <= df.size());
+ btVector3 grad_N_hat_1st_col = btVector3(-1,-1,-1);
+ for (int i = 0; i < m_softBodies.size(); ++i)
+ {
+ btSoftBody* psb = m_softBodies[i];
+ if (!psb->isActive())
+ {
+ continue;
+ }
+ for (int j = 0; j < psb->m_tetras.size(); ++j)
+ {
+ btSoftBody::Tetra& tetra = psb->m_tetras[j];
+ btSoftBody::Node* node0 = tetra.m_n[0];
+ btSoftBody::Node* node1 = tetra.m_n[1];
+ btSoftBody::Node* node2 = tetra.m_n[2];
+ btSoftBody::Node* node3 = tetra.m_n[3];
+ size_t id0 = node0->index;
+ size_t id1 = node1->index;
+ size_t id2 = node2->index;
+ size_t id3 = node3->index;
+ btMatrix3x3 dF = Ds(id0, id1, id2, id3, dx) * tetra.m_Dm_inverse;
+ btMatrix3x3 dP;
+ firstPiolaDifferential(psb->m_tetraScratches[j], dF, dP);
+// btVector3 df_on_node0 = dP * (tetra.m_Dm_inverse.transpose()*grad_N_hat_1st_col);
+ btMatrix3x3 df_on_node123 = dP * tetra.m_Dm_inverse.transpose();
+ btVector3 df_on_node0 = df_on_node123 * grad_N_hat_1st_col;
+
+ // elastic force differential
+ btScalar scale1 = scale * tetra.m_element_measure;
+ df[id0] -= scale1 * df_on_node0;
+ df[id1] -= scale1 * df_on_node123.getColumn(0);
+ df[id2] -= scale1 * df_on_node123.getColumn(1);
+ df[id3] -= scale1 * df_on_node123.getColumn(2);
+ }
+ }
+ }
+
+ void firstPiola(const btSoftBody::TetraScratch& s, btMatrix3x3& P)
+ {
+ btScalar c1 = (m_mu * ( 1. - 1. / (s.m_trace + 1.)));
+ btScalar c2 = (m_lambda * (s.m_J - 1.) - 0.75 * m_mu);
+ P = s.m_F * c1 + s.m_cofF * c2;
+ }
+
+ // Let P be the first piola stress.
+ // This function calculates the dP = dP/dF * dF
+ void firstPiolaDifferential(const btSoftBody::TetraScratch& s, const btMatrix3x3& dF, btMatrix3x3& dP)
+ {
+ btScalar c1 = m_mu * ( 1. - 1. / (s.m_trace + 1.));
+ btScalar c2 = (2.*m_mu) * DotProduct(s.m_F, dF) * (1./((1.+s.m_trace)*(1.+s.m_trace)));
+ btScalar c3 = (m_lambda * DotProduct(s.m_cofF, dF));
+ dP = dF * c1 + s.m_F * c2;
+ addScaledCofactorMatrixDifferential(s.m_F, dF, m_lambda*(s.m_J-1.) - 0.75*m_mu, dP);
+ dP += s.m_cofF * c3;
+ }
+
+ // Let Q be the damping stress.
+ // This function calculates the dP = dQ/dF * dF
+ void firstPiolaDampingDifferential(const btSoftBody::TetraScratch& s, const btMatrix3x3& dF, btMatrix3x3& dP)
+ {
+ btScalar c1 = (m_mu_damp * ( 1. - 1. / (s.m_trace + 1.)));
+ btScalar c2 = ((2.*m_mu_damp) * DotProduct(s.m_F, dF) *(1./((1.+s.m_trace)*(1.+s.m_trace))));
+ btScalar c3 = (m_lambda_damp * DotProduct(s.m_cofF, dF));
+ dP = dF * c1 + s.m_F * c2;
+ addScaledCofactorMatrixDifferential(s.m_F, dF, m_lambda_damp*(s.m_J-1.) - 0.75*m_mu_damp, dP);
+ dP += s.m_cofF * c3;
+ }
+
+ btScalar DotProduct(const btMatrix3x3& A, const btMatrix3x3& B)
+ {
+ btScalar ans = 0;
+ for (int i = 0; i < 3; ++i)
+ {
+ ans += A[i].dot(B[i]);
+ }
+ return ans;
+ }
+
+ // Let C(A) be the cofactor of the matrix A
+ // Let H = the derivative of C(A) with respect to A evaluated at F = A
+ // This function calculates H*dF
+ void addScaledCofactorMatrixDifferential(const btMatrix3x3& F, const btMatrix3x3& dF, btScalar scale, btMatrix3x3& M)
+ {
+ M[0][0] += scale * (dF[1][1] * F[2][2] + F[1][1] * dF[2][2] - dF[2][1] * F[1][2] - F[2][1] * dF[1][2]);
+ M[1][0] += scale * (dF[2][1] * F[0][2] + F[2][1] * dF[0][2] - dF[0][1] * F[2][2] - F[0][1] * dF[2][2]);
+ M[2][0] += scale * (dF[0][1] * F[1][2] + F[0][1] * dF[1][2] - dF[1][1] * F[0][2] - F[1][1] * dF[0][2]);
+ M[0][1] += scale * (dF[2][0] * F[1][2] + F[2][0] * dF[1][2] - dF[1][0] * F[2][2] - F[1][0] * dF[2][2]);
+ M[1][1] += scale * (dF[0][0] * F[2][2] + F[0][0] * dF[2][2] - dF[2][0] * F[0][2] - F[2][0] * dF[0][2]);
+ M[2][1] += scale * (dF[1][0] * F[0][2] + F[1][0] * dF[0][2] - dF[0][0] * F[1][2] - F[0][0] * dF[1][2]);
+ M[0][2] += scale * (dF[1][0] * F[2][1] + F[1][0] * dF[2][1] - dF[2][0] * F[1][1] - F[2][0] * dF[1][1]);
+ M[1][2] += scale * (dF[2][0] * F[0][1] + F[2][0] * dF[0][1] - dF[0][0] * F[2][1] - F[0][0] * dF[2][1]);
+ M[2][2] += scale * (dF[0][0] * F[1][1] + F[0][0] * dF[1][1] - dF[1][0] * F[0][1] - F[1][0] * dF[0][1]);
+ }
+
+ virtual btDeformableLagrangianForceType getForceType()
+ {
+ return BT_NEOHOOKEAN_FORCE;
+ }
+
+};
+#endif /* BT_NEOHOOKEAN_H */
diff --git a/thirdparty/bullet/BulletSoftBody/btPreconditioner.h b/thirdparty/bullet/BulletSoftBody/btPreconditioner.h
new file mode 100644
index 0000000000..d712420381
--- /dev/null
+++ b/thirdparty/bullet/BulletSoftBody/btPreconditioner.h
@@ -0,0 +1,79 @@
+/*
+ Written by Xuchen Han <xuchenhan2015@u.northwestern.edu>
+
+ Bullet Continuous Collision Detection and Physics Library
+ Copyright (c) 2019 Google Inc. http://bulletphysics.org
+ 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.
+ */
+
+#ifndef BT_PRECONDITIONER_H
+#define BT_PRECONDITIONER_H
+
+class Preconditioner
+{
+public:
+ typedef btAlignedObjectArray<btVector3> TVStack;
+ virtual void operator()(const TVStack& x, TVStack& b) = 0;
+ virtual void reinitialize(bool nodeUpdated) = 0;
+ virtual ~Preconditioner(){}
+};
+
+class DefaultPreconditioner : public Preconditioner
+{
+public:
+ virtual void operator()(const TVStack& x, TVStack& b)
+ {
+ btAssert(b.size() == x.size());
+ for (int i = 0; i < b.size(); ++i)
+ b[i] = x[i];
+ }
+ virtual void reinitialize(bool nodeUpdated)
+ {
+ }
+
+ virtual ~DefaultPreconditioner(){}
+};
+
+class MassPreconditioner : public Preconditioner
+{
+ btAlignedObjectArray<btScalar> m_inv_mass;
+ const btAlignedObjectArray<btSoftBody *>& m_softBodies;
+public:
+ MassPreconditioner(const btAlignedObjectArray<btSoftBody *>& softBodies)
+ : m_softBodies(softBodies)
+ {
+ }
+
+ virtual void reinitialize(bool nodeUpdated)
+ {
+ if (nodeUpdated)
+ {
+ m_inv_mass.clear();
+ for (int i = 0; i < m_softBodies.size(); ++i)
+ {
+ btSoftBody* psb = m_softBodies[i];
+ for (int j = 0; j < psb->m_nodes.size(); ++j)
+ m_inv_mass.push_back(psb->m_nodes[j].m_im);
+ }
+ }
+ }
+
+ virtual void operator()(const TVStack& x, TVStack& b)
+ {
+ btAssert(b.size() == x.size());
+ btAssert(m_inv_mass.size() == x.size());
+ for (int i = 0; i < b.size(); ++i)
+ {
+ b[i] = x[i] * m_inv_mass[i];
+ }
+ }
+};
+
+#endif /* BT_PRECONDITIONER_H */
diff --git a/thirdparty/bullet/BulletSoftBody/btSoftBody.cpp b/thirdparty/bullet/BulletSoftBody/btSoftBody.cpp
index 7463bdc019..2a458b1d80 100644
--- a/thirdparty/bullet/BulletSoftBody/btSoftBody.cpp
+++ b/thirdparty/bullet/BulletSoftBody/btSoftBody.cpp
@@ -18,9 +18,12 @@ subject to the following restrictions:
#include "BulletSoftBody/btSoftBodySolvers.h"
#include "btSoftBodyData.h"
#include "LinearMath/btSerializer.h"
+#include "LinearMath/btAlignedAllocator.h"
#include "BulletDynamics/Featherstone/btMultiBodyLinkCollider.h"
#include "BulletDynamics/Featherstone/btMultiBodyConstraint.h"
-
+#include "BulletCollision/NarrowPhaseCollision/btGjkEpa2.h"
+#include "BulletCollision/CollisionShapes/btTriangleShape.h"
+#include <iostream>
//
btSoftBody::btSoftBody(btSoftBodyWorldInfo* worldInfo, int node_count, const btVector3* x, const btScalar* m)
: m_softBodySolver(0), m_worldInfo(worldInfo)
@@ -86,6 +89,8 @@ void btSoftBody::initDefaults()
m_cfg.piterations = 1;
m_cfg.diterations = 0;
m_cfg.citerations = 4;
+ m_cfg.drag = 0;
+ m_cfg.m_maxStress = 0;
m_cfg.collisions = fCollision::Default;
m_pose.m_bvolume = false;
m_pose.m_bframe = false;
@@ -110,6 +115,11 @@ void btSoftBody::initDefaults()
m_windVelocity = btVector3(0, 0, 0);
m_restLengthScale = btScalar(1.0);
+ m_dampingCoefficient = 1;
+ m_sleepingThreshold = 0.1;
+ m_useFaceContact = true;
+ m_useSelfCollision = false;
+ m_collisionFlags = 0;
}
//
@@ -315,7 +325,7 @@ void btSoftBody::appendFace(int model, Material* mat)
ZeroInitialize(f);
f.m_material = mat ? mat : m_materials[0];
}
- m_faces.push_back(f);
+ m_faces.push_back(f);
}
//
@@ -402,6 +412,98 @@ void btSoftBody::appendAnchor(int node, btRigidBody* body, const btVector3& loca
}
//
+void btSoftBody::appendDeformableAnchor(int node, btRigidBody* body)
+{
+ DeformableNodeRigidAnchor c;
+ btSoftBody::Node& n = m_nodes[node];
+ const btScalar ima = n.m_im;
+ const btScalar imb = body->getInvMass();
+ btVector3 nrm;
+ const btCollisionShape* shp = body->getCollisionShape();
+ const btTransform& wtr = body->getWorldTransform();
+ btScalar dst =
+ m_worldInfo->m_sparsesdf.Evaluate(
+ wtr.invXform(m_nodes[node].m_x),
+ shp,
+ nrm,
+ 0);
+
+ c.m_cti.m_colObj = body;
+ c.m_cti.m_normal = wtr.getBasis() * nrm;
+ c.m_cti.m_offset = dst;
+ c.m_node = &m_nodes[node];
+ const btScalar fc = m_cfg.kDF * body->getFriction();
+ c.m_c2 = ima;
+ c.m_c3 = fc;
+ c.m_c4 = body->isStaticOrKinematicObject() ? m_cfg.kKHR : m_cfg.kCHR;
+ static const btMatrix3x3 iwiStatic(0, 0, 0, 0, 0, 0, 0, 0, 0);
+ const btMatrix3x3& iwi = body->getInvInertiaTensorWorld();
+ const btVector3 ra = n.m_x - wtr.getOrigin();
+
+ c.m_c0 = ImpulseMatrix(1, ima, imb, iwi, ra);
+ c.m_c1 = ra;
+ c.m_local = body->getWorldTransform().inverse() * m_nodes[node].m_x;
+ c.m_node->m_battach = 1;
+ m_deformableAnchors.push_back(c);
+}
+
+//
+void btSoftBody::appendDeformableAnchor(int node, btMultiBodyLinkCollider* link)
+{
+ DeformableNodeRigidAnchor c;
+ btSoftBody::Node& n = m_nodes[node];
+ const btScalar ima = n.m_im;
+ btVector3 nrm;
+ const btCollisionShape* shp = link->getCollisionShape();
+ const btTransform& wtr = link->getWorldTransform();
+ btScalar dst =
+ m_worldInfo->m_sparsesdf.Evaluate(
+ wtr.invXform(m_nodes[node].m_x),
+ shp,
+ nrm,
+ 0);
+ c.m_cti.m_colObj = link;
+ c.m_cti.m_normal = wtr.getBasis() * nrm;
+ c.m_cti.m_offset = dst;
+ c.m_node = &m_nodes[node];
+ const btScalar fc = m_cfg.kDF * link->getFriction();
+ c.m_c2 = ima;
+ c.m_c3 = fc;
+ c.m_c4 = link->isStaticOrKinematicObject() ? m_cfg.kKHR : m_cfg.kCHR;
+ btVector3 normal = c.m_cti.m_normal;
+ btVector3 t1 = generateUnitOrthogonalVector(normal);
+ btVector3 t2 = btCross(normal, t1);
+ btMultiBodyJacobianData jacobianData_normal, jacobianData_t1, jacobianData_t2;
+ findJacobian(link, jacobianData_normal, c.m_node->m_x, normal);
+ findJacobian(link, jacobianData_t1, c.m_node->m_x, t1);
+ findJacobian(link, jacobianData_t2, c.m_node->m_x, t2);
+
+ btScalar* J_n = &jacobianData_normal.m_jacobians[0];
+ btScalar* J_t1 = &jacobianData_t1.m_jacobians[0];
+ btScalar* J_t2 = &jacobianData_t2.m_jacobians[0];
+
+ btScalar* u_n = &jacobianData_normal.m_deltaVelocitiesUnitImpulse[0];
+ btScalar* u_t1 = &jacobianData_t1.m_deltaVelocitiesUnitImpulse[0];
+ btScalar* u_t2 = &jacobianData_t2.m_deltaVelocitiesUnitImpulse[0];
+
+ btMatrix3x3 rot(normal.getX(), normal.getY(), normal.getZ(),
+ t1.getX(), t1.getY(), t1.getZ(),
+ t2.getX(), t2.getY(), t2.getZ()); // world frame to local frame
+ const int ndof = link->m_multiBody->getNumDofs() + 6;
+ btMatrix3x3 local_impulse_matrix = (Diagonal(n.m_im) + OuterProduct(J_n, J_t1, J_t2, u_n, u_t1, u_t2, ndof)).inverse();
+ c.m_c0 = rot.transpose() * local_impulse_matrix * rot;
+ c.jacobianData_normal = jacobianData_normal;
+ c.jacobianData_t1 = jacobianData_t1;
+ c.jacobianData_t2 = jacobianData_t2;
+ c.t1 = t1;
+ c.t2 = t2;
+ const btVector3 ra = n.m_x - wtr.getOrigin();
+ c.m_c1 = ra;
+ c.m_local = link->getWorldTransform().inverse() * m_nodes[node].m_x;
+ c.m_node->m_battach = 1;
+ m_deformableAnchors.push_back(c);
+}
+//
void btSoftBody::appendLinearJoint(const LJoint::Specs& specs, Cluster* body0, Body body1)
{
LJoint* pj = new (btAlignedAlloc(sizeof(LJoint), 16)) LJoint();
@@ -518,7 +620,7 @@ void btSoftBody::addAeroForceToNode(const btVector3& windVelocity, int nodeIndex
fDrag = 0.5f * kDG * medium.m_density * rel_v2 * tri_area * n_dot_v * (-rel_v_nrm);
// Check angle of attack
- // cos(10°) = 0.98480
+ // cos(10º) = 0.98480
if (0 < n_dot_v && n_dot_v < 0.98480f)
fLift = 0.5f * kLF * medium.m_density * rel_v_len * tri_area * btSqrt(1.0f - n_dot_v * n_dot_v) * (nrm.cross(rel_v_nrm).cross(rel_v_nrm));
@@ -604,7 +706,7 @@ void btSoftBody::addAeroForceToFace(const btVector3& windVelocity, int faceIndex
fDrag = 0.5f * kDG * medium.m_density * rel_v2 * tri_area * n_dot_v * (-rel_v_nrm);
// Check angle of attack
- // cos(10°) = 0.98480
+ // cos(10º) = 0.98480
if (0 < n_dot_v && n_dot_v < 0.98480f)
fLift = 0.5f * kLF * medium.m_density * rel_v_len * tri_area * btSqrt(1.0f - n_dot_v * n_dot_v) * (nrm.cross(rel_v_nrm).cross(rel_v_nrm));
@@ -853,6 +955,7 @@ void btSoftBody::scale(const btVector3& scl)
updateNormals();
updateBounds();
updateConstants();
+ initializeDmInverse();
}
//
@@ -1757,115 +1860,115 @@ void btSoftBody::setSolver(eSolverPresets::_ preset)
}
}
-//
void btSoftBody::predictMotion(btScalar dt)
{
- int i, ni;
-
- /* Update */
- if (m_bUpdateRtCst)
- {
- m_bUpdateRtCst = false;
- updateConstants();
- m_fdbvt.clear();
- if (m_cfg.collisions & fCollision::VF_SS)
- {
- initializeFaceTree();
- }
- }
-
- /* Prepare */
- m_sst.sdt = dt * m_cfg.timescale;
- m_sst.isdt = 1 / m_sst.sdt;
- m_sst.velmrg = m_sst.sdt * 3;
- m_sst.radmrg = getCollisionShape()->getMargin();
- m_sst.updmrg = m_sst.radmrg * (btScalar)0.25;
- /* Forces */
- addVelocity(m_worldInfo->m_gravity * m_sst.sdt);
- applyForces();
- /* Integrate */
- for (i = 0, ni = m_nodes.size(); i < ni; ++i)
- {
- Node& n = m_nodes[i];
- n.m_q = n.m_x;
- btVector3 deltaV = n.m_f * n.m_im * m_sst.sdt;
- {
- btScalar maxDisplacement = m_worldInfo->m_maxDisplacement;
- btScalar clampDeltaV = maxDisplacement / m_sst.sdt;
- for (int c = 0; c < 3; c++)
- {
- if (deltaV[c] > clampDeltaV)
- {
- deltaV[c] = clampDeltaV;
- }
- if (deltaV[c] < -clampDeltaV)
- {
- deltaV[c] = -clampDeltaV;
- }
- }
- }
- n.m_v += deltaV;
- n.m_x += n.m_v * m_sst.sdt;
- n.m_f = btVector3(0, 0, 0);
- }
- /* Clusters */
- updateClusters();
- /* Bounds */
- updateBounds();
- /* Nodes */
- ATTRIBUTE_ALIGNED16(btDbvtVolume)
- vol;
- for (i = 0, ni = m_nodes.size(); i < ni; ++i)
- {
- Node& n = m_nodes[i];
- vol = btDbvtVolume::FromCR(n.m_x, m_sst.radmrg);
- m_ndbvt.update(n.m_leaf,
- vol,
- n.m_v * m_sst.velmrg,
- m_sst.updmrg);
- }
- /* Faces */
- if (!m_fdbvt.empty())
- {
- for (int i = 0; i < m_faces.size(); ++i)
- {
- Face& f = m_faces[i];
- const btVector3 v = (f.m_n[0]->m_v +
- f.m_n[1]->m_v +
- f.m_n[2]->m_v) /
- 3;
- vol = VolumeOf(f, m_sst.radmrg);
- m_fdbvt.update(f.m_leaf,
- vol,
- v * m_sst.velmrg,
- m_sst.updmrg);
- }
- }
- /* Pose */
- updatePose();
- /* Match */
- if (m_pose.m_bframe && (m_cfg.kMT > 0))
- {
- const btMatrix3x3 posetrs = m_pose.m_rot;
- for (int i = 0, ni = m_nodes.size(); i < ni; ++i)
- {
- Node& n = m_nodes[i];
- if (n.m_im > 0)
- {
- const btVector3 x = posetrs * m_pose.m_pos[i] + m_pose.m_com;
- n.m_x = Lerp(n.m_x, x, m_cfg.kMT);
- }
- }
- }
- /* Clear contacts */
- m_rcontacts.resize(0);
- m_scontacts.resize(0);
- /* Optimize dbvt's */
- m_ndbvt.optimizeIncremental(1);
- m_fdbvt.optimizeIncremental(1);
- m_cdbvt.optimizeIncremental(1);
+ int i, ni;
+
+ /* Update */
+ if (m_bUpdateRtCst)
+ {
+ m_bUpdateRtCst = false;
+ updateConstants();
+ m_fdbvt.clear();
+ if (m_cfg.collisions & fCollision::VF_SS)
+ {
+ initializeFaceTree();
+ }
+ }
+
+ /* Prepare */
+ m_sst.sdt = dt * m_cfg.timescale;
+ m_sst.isdt = 1 / m_sst.sdt;
+ m_sst.velmrg = m_sst.sdt * 3;
+ m_sst.radmrg = getCollisionShape()->getMargin();
+ m_sst.updmrg = m_sst.radmrg * (btScalar)0.25;
+ /* Forces */
+ addVelocity(m_worldInfo->m_gravity * m_sst.sdt);
+ applyForces();
+ /* Integrate */
+ for (i = 0, ni = m_nodes.size(); i < ni; ++i)
+ {
+ Node& n = m_nodes[i];
+ n.m_q = n.m_x;
+ btVector3 deltaV = n.m_f * n.m_im * m_sst.sdt;
+ {
+ btScalar maxDisplacement = m_worldInfo->m_maxDisplacement;
+ btScalar clampDeltaV = maxDisplacement / m_sst.sdt;
+ for (int c = 0; c < 3; c++)
+ {
+ if (deltaV[c] > clampDeltaV)
+ {
+ deltaV[c] = clampDeltaV;
+ }
+ if (deltaV[c] < -clampDeltaV)
+ {
+ deltaV[c] = -clampDeltaV;
+ }
+ }
+ }
+ n.m_v += deltaV;
+ n.m_x += n.m_v * m_sst.sdt;
+ n.m_f = btVector3(0, 0, 0);
+ }
+ /* Clusters */
+ updateClusters();
+ /* Bounds */
+ updateBounds();
+ /* Nodes */
+ ATTRIBUTE_ALIGNED16(btDbvtVolume)
+ vol;
+ for (i = 0, ni = m_nodes.size(); i < ni; ++i)
+ {
+ Node& n = m_nodes[i];
+ vol = btDbvtVolume::FromCR(n.m_x, m_sst.radmrg);
+ m_ndbvt.update(n.m_leaf,
+ vol,
+ n.m_v * m_sst.velmrg,
+ m_sst.updmrg);
+ }
+ /* Faces */
+ if (!m_fdbvt.empty())
+ {
+ for (int i = 0; i < m_faces.size(); ++i)
+ {
+ Face& f = m_faces[i];
+ const btVector3 v = (f.m_n[0]->m_v +
+ f.m_n[1]->m_v +
+ f.m_n[2]->m_v) /
+ 3;
+ vol = VolumeOf(f, m_sst.radmrg);
+ m_fdbvt.update(f.m_leaf,
+ vol,
+ v * m_sst.velmrg,
+ m_sst.updmrg);
+ }
+ }
+ /* Pose */
+ updatePose();
+ /* Match */
+ if (m_pose.m_bframe && (m_cfg.kMT > 0))
+ {
+ const btMatrix3x3 posetrs = m_pose.m_rot;
+ for (int i = 0, ni = m_nodes.size(); i < ni; ++i)
+ {
+ Node& n = m_nodes[i];
+ if (n.m_im > 0)
+ {
+ const btVector3 x = posetrs * m_pose.m_pos[i] + m_pose.m_com;
+ n.m_x = Lerp(n.m_x, x, m_cfg.kMT);
+ }
+ }
+ }
+ /* Clear contacts */
+ m_rcontacts.resize(0);
+ m_scontacts.resize(0);
+ /* Optimize dbvt's */
+ m_ndbvt.optimizeIncremental(1);
+ m_fdbvt.optimizeIncremental(1);
+ m_cdbvt.optimizeIncremental(1);
}
+
//
void btSoftBody::solveConstraints()
{
@@ -2261,36 +2364,195 @@ btVector3 btSoftBody::evaluateCom() const
return (com);
}
-//
bool btSoftBody::checkContact(const btCollisionObjectWrapper* colObjWrap,
+ const btVector3& x,
+ btScalar margin,
+ btSoftBody::sCti& cti) const
+{
+ btVector3 nrm;
+ const btCollisionShape* shp = colObjWrap->getCollisionShape();
+ // const btRigidBody *tmpRigid = btRigidBody::upcast(colObjWrap->getCollisionObject());
+ //const btTransform &wtr = tmpRigid ? tmpRigid->getWorldTransform() : colObjWrap->getWorldTransform();
+ const btTransform& wtr = colObjWrap->getWorldTransform();
+ //todo: check which transform is needed here
+
+ btScalar dst =
+ m_worldInfo->m_sparsesdf.Evaluate(
+ wtr.invXform(x),
+ shp,
+ nrm,
+ margin);
+ if (dst < 0)
+ {
+ cti.m_colObj = colObjWrap->getCollisionObject();
+ cti.m_normal = wtr.getBasis() * nrm;
+ cti.m_offset = -btDot(cti.m_normal, x - cti.m_normal * dst);
+ return (true);
+ }
+ return (false);
+}
+
+//
+bool btSoftBody::checkDeformableContact(const btCollisionObjectWrapper* colObjWrap,
const btVector3& x,
btScalar margin,
- btSoftBody::sCti& cti) const
+ btSoftBody::sCti& cti, bool predict) const
{
btVector3 nrm;
const btCollisionShape* shp = colObjWrap->getCollisionShape();
- // const btRigidBody *tmpRigid = btRigidBody::upcast(colObjWrap->getCollisionObject());
- //const btTransform &wtr = tmpRigid ? tmpRigid->getWorldTransform() : colObjWrap->getWorldTransform();
- const btTransform& wtr = colObjWrap->getWorldTransform();
- //todo: check which transform is needed here
-
+ const btCollisionObject* tmpCollisionObj = colObjWrap->getCollisionObject();
+ // use the position x_{n+1}^* = x_n + dt * v_{n+1}^* where v_{n+1}^* = v_n + dtg for collision detect
+ // but resolve contact at x_n
+// btTransform wtr = (predict) ?
+// (colObjWrap->m_preTransform != NULL ? tmpCollisionObj->getInterpolationWorldTransform()*(*colObjWrap->m_preTransform) : tmpCollisionObj->getInterpolationWorldTransform())
+// : colObjWrap->getWorldTransform();
+ const btTransform& wtr = colObjWrap->getWorldTransform();
btScalar dst =
m_worldInfo->m_sparsesdf.Evaluate(
wtr.invXform(x),
shp,
nrm,
margin);
- if (dst < 0)
+ if (!predict)
{
cti.m_colObj = colObjWrap->getCollisionObject();
cti.m_normal = wtr.getBasis() * nrm;
- cti.m_offset = -btDot(cti.m_normal, x - cti.m_normal * dst);
- return (true);
+ cti.m_offset = dst;
}
+ if (dst < 0)
+ return true;
return (false);
}
//
+// Compute barycentric coordinates (u, v, w) for
+// point p with respect to triangle (a, b, c)
+static void getBarycentric(const btVector3& p, btVector3& a, btVector3& b, btVector3& c, btVector3& bary)
+{
+ btVector3 v0 = b - a, v1 = c - a, v2 = p - a;
+ btScalar d00 = v0.dot(v0);
+ btScalar d01 = v0.dot(v1);
+ btScalar d11 = v1.dot(v1);
+ btScalar d20 = v2.dot(v0);
+ btScalar d21 = v2.dot(v1);
+ btScalar denom = d00 * d11 - d01 * d01;
+ bary.setY((d11 * d20 - d01 * d21) / denom);
+ bary.setZ((d00 * d21 - d01 * d20) / denom);
+ bary.setX(btScalar(1) - bary.getY() - bary.getZ());
+}
+
+//
+bool btSoftBody::checkDeformableFaceContact(const btCollisionObjectWrapper* colObjWrap,
+ Face& f,
+ btVector3& contact_point,
+ btVector3& bary,
+ btScalar margin,
+ btSoftBody::sCti& cti, bool predict) const
+{
+ btVector3 nrm;
+ const btCollisionShape* shp = colObjWrap->getCollisionShape();
+ const btCollisionObject* tmpCollisionObj = colObjWrap->getCollisionObject();
+ // use the position x_{n+1}^* = x_n + dt * v_{n+1}^* where v_{n+1}^* = v_n + dtg for collision detect
+ // but resolve contact at x_n
+ btTransform wtr = (predict) ?
+ (colObjWrap->m_preTransform != NULL ? tmpCollisionObj->getInterpolationWorldTransform()*(*colObjWrap->m_preTransform) : tmpCollisionObj->getInterpolationWorldTransform())
+ : colObjWrap->getWorldTransform();
+// const btTransform& wtr = colObjWrap->getWorldTransform();
+ btScalar dst;
+
+//#define USE_QUADRATURE 1
+//#define CACHE_PREV_COLLISION
+
+ // use the contact position of the previous collision
+#ifdef CACHE_PREV_COLLISION
+ if (f.m_pcontact[3] != 0)
+ {
+ for (int i = 0; i < 3; ++i)
+ bary[i] = f.m_pcontact[i];
+ contact_point = BaryEval(f.m_n[0]->m_x, f.m_n[1]->m_x, f.m_n[2]->m_x, bary);
+ dst = m_worldInfo->m_sparsesdf.Evaluate(
+ wtr.invXform(contact_point),
+ shp,
+ nrm,
+ margin);
+ nrm = wtr.getBasis() * nrm;
+ // use cached contact point
+ }
+ else
+ {
+ btGjkEpaSolver2::sResults results;
+ btTransform triangle_transform;
+ triangle_transform.setIdentity();
+ triangle_transform.setOrigin(f.m_n[0]->m_x);
+ btTriangleShape triangle(btVector3(0,0,0), f.m_n[1]->m_x-f.m_n[0]->m_x, f.m_n[2]->m_x-f.m_n[0]->m_x);
+ btVector3 guess(0,0,0);
+ const btConvexShape* csh = static_cast<const btConvexShape*>(shp);
+ btGjkEpaSolver2::SignedDistance(&triangle, triangle_transform, csh, wtr, guess, results);
+ dst = results.distance - margin;
+ contact_point = results.witnesses[0];
+ getBarycentric(contact_point, f.m_n[0]->m_x, f.m_n[1]->m_x, f.m_n[2]->m_x, bary);
+ nrm = results.normal;
+ for (int i = 0; i < 3; ++i)
+ f.m_pcontact[i] = bary[i];
+ }
+
+#endif
+
+ // use collision quadrature point
+#ifdef USE_QUADRATURE
+ {
+ dst = SIMD_INFINITY;
+ btVector3 local_nrm;
+ for (int q = 0; q < m_quads.size(); ++q)
+ {
+ btVector3 p = BaryEval(f.m_n[0]->m_x, f.m_n[1]->m_x, f.m_n[2]->m_x, m_quads[q]);
+ btScalar local_dst = m_worldInfo->m_sparsesdf.Evaluate(
+ wtr.invXform(p),
+ shp,
+ local_nrm,
+ margin);
+ if (local_dst < dst)
+ {
+ dst = local_dst;
+ contact_point = p;
+ bary = m_quads[q];
+ nrm = wtr.getBasis() * local_nrm;
+ }
+ }
+ }
+#endif
+
+ // regular face contact
+ {
+ btGjkEpaSolver2::sResults results;
+ btTransform triangle_transform;
+ triangle_transform.setIdentity();
+ triangle_transform.setOrigin(f.m_n[0]->m_x);
+ btTriangleShape triangle(btVector3(0,0,0), f.m_n[1]->m_x-f.m_n[0]->m_x, f.m_n[2]->m_x-f.m_n[0]->m_x);
+ btVector3 guess(0,0,0);
+ const btConvexShape* csh = static_cast<const btConvexShape*>(shp);
+ btGjkEpaSolver2::SignedDistance(&triangle, triangle_transform, csh, wtr, guess, results);
+ dst = results.distance - margin;
+ contact_point = results.witnesses[0];
+ getBarycentric(contact_point, f.m_n[0]->m_x, f.m_n[1]->m_x, f.m_n[2]->m_x, bary);
+ nrm = results.normal;
+ for (int i = 0; i < 3; ++i)
+ f.m_pcontact[i] = bary[i];
+ }
+
+ if (!predict)
+ {
+ cti.m_colObj = colObjWrap->getCollisionObject();
+ cti.m_normal = nrm;
+ cti.m_offset = dst;
+ }
+
+ if (dst < 0)
+ return true;
+ return (false);
+}
+
+//
void btSoftBody::updateNormals()
{
const btVector3 zv(0, 0, 0);
@@ -2305,7 +2567,8 @@ void btSoftBody::updateNormals()
btSoftBody::Face& f = m_faces[i];
const btVector3 n = btCross(f.m_n[1]->m_x - f.m_n[0]->m_x,
f.m_n[2]->m_x - f.m_n[0]->m_x);
- f.m_normal = n.normalized();
+ f.m_normal = n;
+ f.m_normal.safeNormalize();
f.m_n[0]->m_n += n;
f.m_n[1]->m_n += n;
f.m_n[2]->m_n += n;
@@ -2333,31 +2596,63 @@ void btSoftBody::updateBounds()
m_bounds[1] = btVector3(1000, 1000, 1000);
} else {*/
- if (m_ndbvt.m_root)
- {
- const btVector3& mins = m_ndbvt.m_root->volume.Mins();
- const btVector3& maxs = m_ndbvt.m_root->volume.Maxs();
- const btScalar csm = getCollisionShape()->getMargin();
- const btVector3 mrg = btVector3(csm,
- csm,
- csm) *
- 1; // ??? to investigate...
- m_bounds[0] = mins - mrg;
- m_bounds[1] = maxs + mrg;
- if (0 != getBroadphaseHandle())
- {
- m_worldInfo->m_broadphase->setAabb(getBroadphaseHandle(),
- m_bounds[0],
- m_bounds[1],
- m_worldInfo->m_dispatcher);
- }
- }
- else
- {
- m_bounds[0] =
- m_bounds[1] = btVector3(0, 0, 0);
- }
- //}
+// if (m_ndbvt.m_root)
+// {
+// const btVector3& mins = m_ndbvt.m_root->volume.Mins();
+// const btVector3& maxs = m_ndbvt.m_root->volume.Maxs();
+// const btScalar csm = getCollisionShape()->getMargin();
+// const btVector3 mrg = btVector3(csm,
+// csm,
+// csm) *
+// 1; // ??? to investigate...
+// m_bounds[0] = mins - mrg;
+// m_bounds[1] = maxs + mrg;
+// if (0 != getBroadphaseHandle())
+// {
+// m_worldInfo->m_broadphase->setAabb(getBroadphaseHandle(),
+// m_bounds[0],
+// m_bounds[1],
+// m_worldInfo->m_dispatcher);
+// }
+// }
+// else
+// {
+// m_bounds[0] =
+// m_bounds[1] = btVector3(0, 0, 0);
+// }
+ if (m_nodes.size())
+ {
+ btVector3 mins = m_nodes[0].m_x;
+ btVector3 maxs = m_nodes[0].m_x;
+ for (int i = 1; i < m_nodes.size(); ++i)
+ {
+ for (int d = 0; d < 3; ++d)
+ {
+ if (m_nodes[i].m_x[d] > maxs[d])
+ maxs[d] = m_nodes[i].m_x[d];
+ if (m_nodes[i].m_x[d] < mins[d])
+ mins[d] = m_nodes[i].m_x[d];
+ }
+ }
+ const btScalar csm = getCollisionShape()->getMargin();
+ const btVector3 mrg = btVector3(csm,
+ csm,
+ csm);
+ m_bounds[0] = mins - mrg;
+ m_bounds[1] = maxs + mrg;
+ if (0 != getBroadphaseHandle())
+ {
+ m_worldInfo->m_broadphase->setAabb(getBroadphaseHandle(),
+ m_bounds[0],
+ m_bounds[1],
+ m_worldInfo->m_dispatcher);
+ }
+ }
+ else
+ {
+ m_bounds[0] =
+ m_bounds[1] = btVector3(0, 0, 0);
+ }
}
//
@@ -2774,6 +3069,62 @@ void btSoftBody::dampClusters()
}
}
+void btSoftBody::setSpringStiffness(btScalar k)
+{
+ for (int i = 0; i < m_links.size(); ++i)
+ {
+ m_links[i].Feature::m_material->m_kLST = k;
+ }
+}
+
+void btSoftBody::initializeDmInverse()
+{
+ btScalar unit_simplex_measure = 1./6.;
+
+ for (int i = 0; i < m_tetras.size(); ++i)
+ {
+ Tetra &t = m_tetras[i];
+ btVector3 c1 = t.m_n[1]->m_x - t.m_n[0]->m_x;
+ btVector3 c2 = t.m_n[2]->m_x - t.m_n[0]->m_x;
+ btVector3 c3 = t.m_n[3]->m_x - t.m_n[0]->m_x;
+ btMatrix3x3 Dm(c1.getX(), c2.getX(), c3.getX(),
+ c1.getY(), c2.getY(), c3.getY(),
+ c1.getZ(), c2.getZ(), c3.getZ());
+ t.m_element_measure = Dm.determinant() * unit_simplex_measure;
+ t.m_Dm_inverse = Dm.inverse();
+ }
+}
+
+void btSoftBody::updateDeformation()
+{
+ for (int i = 0; i < m_tetras.size(); ++i)
+ {
+ btSoftBody::Tetra& t = m_tetras[i];
+ btVector3 c1 = t.m_n[1]->m_q - t.m_n[0]->m_q;
+ btVector3 c2 = t.m_n[2]->m_q - t.m_n[0]->m_q;
+ btVector3 c3 = t.m_n[3]->m_q - t.m_n[0]->m_q;
+ btMatrix3x3 Ds(c1.getX(), c2.getX(), c3.getX(),
+ c1.getY(), c2.getY(), c3.getY(),
+ c1.getZ(), c2.getZ(), c3.getZ());
+ t.m_F = Ds * t.m_Dm_inverse;
+
+ btSoftBody::TetraScratch& s = m_tetraScratches[i];
+ s.m_F = t.m_F;
+ s.m_J = t.m_F.determinant();
+ btMatrix3x3 C = t.m_F.transpose()*t.m_F;
+ s.m_trace = C[0].getX() + C[1].getY() + C[2].getZ();
+ s.m_cofF = t.m_F.adjoint().transpose();
+ }
+}
+
+void btSoftBody::advanceDeformation()
+{
+ updateDeformation();
+ for (int i = 0; i < m_tetras.size(); ++i)
+ {
+ m_tetraScratchesTn[i] = m_tetraScratches[i];
+ }
+}
//
void btSoftBody::Joint::Prepare(btScalar dt, int)
{
@@ -3013,6 +3364,40 @@ void btSoftBody::applyForces()
}
//
+void btSoftBody::setMaxStress(btScalar maxStress)
+{
+ m_cfg.m_maxStress = maxStress;
+}
+
+//
+void btSoftBody::interpolateRenderMesh()
+{
+ for (int i = 0; i < m_renderNodes.size(); ++i)
+ {
+ Node& n = m_renderNodes[i];
+ n.m_x.setZero();
+ for (int j = 0; j < 4; ++j)
+ {
+ if (m_renderNodesParents[i].size())
+ {
+ n.m_x += m_renderNodesParents[i][j]->m_x * m_renderNodesInterpolationWeights[i][j];
+ }
+ }
+ }
+}
+
+void btSoftBody::setCollisionQuadrature(int N)
+{
+ for (int i = 0; i <= N; ++i)
+ {
+ for (int j = 0; i+j <= N; ++j)
+ {
+ m_quads.push_back(btVector3(btScalar(i)/btScalar(N), btScalar(j)/btScalar(N), btScalar(N-i-j)/btScalar(N)));
+ }
+ }
+}
+
+//
void btSoftBody::PSolve_Anchors(btSoftBody* psb, btScalar kst, btScalar ti)
{
BT_PROFILE("PSolve_Anchors");
@@ -3214,6 +3599,16 @@ btSoftBody::vsolver_t btSoftBody::getSolver(eVSolver::_ solver)
return (0);
}
+void btSoftBody::setSelfCollision(bool useSelfCollision)
+{
+ m_useSelfCollision = useSelfCollision;
+}
+
+bool btSoftBody::useSelfCollision()
+{
+ return m_useSelfCollision;
+}
+
//
void btSoftBody::defaultCollisionHandler(const btCollisionObjectWrapper* pcoWrap)
{
@@ -3252,12 +3647,99 @@ void btSoftBody::defaultCollisionHandler(const btCollisionObjectWrapper* pcoWrap
collider.ProcessColObj(this, pcoWrap);
}
break;
+ case fCollision::SDF_RD:
+ {
+
+ btRigidBody* prb1 = (btRigidBody*)btRigidBody::upcast(pcoWrap->getCollisionObject());
+ if (pcoWrap->getCollisionObject()->isActive() || this->isActive())
+ {
+ const btTransform wtr = pcoWrap->getWorldTransform();
+// const btTransform ctr = pcoWrap->getWorldTransform();
+// const btScalar timemargin = (wtr.getOrigin() - ctr.getOrigin()).length();
+ const btScalar timemargin = 0;
+ const btScalar basemargin = getCollisionShape()->getMargin();
+ btVector3 mins;
+ btVector3 maxs;
+ ATTRIBUTE_ALIGNED16(btDbvtVolume)
+ volume;
+ pcoWrap->getCollisionShape()->getAabb(wtr,
+ mins,
+ maxs);
+ volume = btDbvtVolume::FromMM(mins, maxs);
+ volume.Expand(btVector3(basemargin, basemargin, basemargin));
+ btSoftColliders::CollideSDF_RD docollideNode;
+ docollideNode.psb = this;
+ docollideNode.m_colObj1Wrap = pcoWrap;
+ docollideNode.m_rigidBody = prb1;
+ docollideNode.dynmargin = basemargin + timemargin;
+ docollideNode.stamargin = basemargin;
+ m_ndbvt.collideTV(m_ndbvt.m_root, volume, docollideNode);
+
+ if (this->m_useFaceContact)
+ {
+ btSoftColliders::CollideSDF_RDF docollideFace;
+ docollideFace.psb = this;
+ docollideFace.m_colObj1Wrap = pcoWrap;
+ docollideFace.m_rigidBody = prb1;
+ docollideFace.dynmargin = basemargin + timemargin;
+ docollideFace.stamargin = basemargin;
+ m_fdbvt.collideTV(m_fdbvt.m_root, volume, docollideFace);
+ }
+ }
+ }
+ break;
}
}
+static inline btDbvntNode* copyToDbvnt(const btDbvtNode* n)
+{
+ if (n == 0)
+ return 0;
+ btDbvntNode* root = new btDbvntNode(n);
+ if (n->isinternal())
+ {
+ btDbvntNode* c0 = copyToDbvnt(n->childs[0]);
+ root->childs[0] = c0;
+ btDbvntNode* c1 = copyToDbvnt(n->childs[1]);
+ root->childs[1] = c1;
+ }
+ return root;
+}
+
+static inline void calculateNormalCone(btDbvntNode* root)
+{
+ if (!root)
+ return;
+ if (root->isleaf())
+ {
+ const btSoftBody::Face* face = (btSoftBody::Face*)root->data;
+ root->normal = face->m_normal;
+ root->angle = 0;
+ }
+ else
+ {
+ btVector3 n0(0,0,0), n1(0,0,0);
+ btScalar a0 = 0, a1 = 0;
+ if (root->childs[0])
+ {
+ calculateNormalCone(root->childs[0]);
+ n0 = root->childs[0]->normal;
+ a0 = root->childs[0]->angle;
+ }
+ if (root->childs[1])
+ {
+ calculateNormalCone(root->childs[1]);
+ n1 = root->childs[1]->normal;
+ a1 = root->childs[1]->angle;
+ }
+ root->normal = (n0+n1).safeNormalize();
+ root->angle = btMax(a0,a1) + btAngle(n0, n1)*0.5;
+ }
+}
//
void btSoftBody::defaultCollisionHandler(btSoftBody* psb)
{
+ BT_PROFILE("Deformable Collision");
const int cf = m_cfg.collisions & psb->m_cfg.collisions;
switch (cf & fCollision::SVSmask)
{
@@ -3295,6 +3777,60 @@ void btSoftBody::defaultCollisionHandler(btSoftBody* psb)
}
}
break;
+ case fCollision::VF_DD:
+ {
+ if (psb->isActive() || this->isActive())
+ {
+ if (this != psb)
+ {
+ btSoftColliders::CollideVF_DD docollide;
+ /* common */
+ docollide.mrg = getCollisionShape()->getMargin() +
+ psb->getCollisionShape()->getMargin();
+ /* psb0 nodes vs psb1 faces */
+ if (psb->m_tetras.size() > 0)
+ docollide.useFaceNormal = true;
+ else
+ docollide.useFaceNormal = false;
+ docollide.psb[0] = this;
+ docollide.psb[1] = psb;
+ docollide.psb[0]->m_ndbvt.collideTT(docollide.psb[0]->m_ndbvt.m_root,
+ docollide.psb[1]->m_fdbvt.m_root,
+ docollide);
+ /* psb1 nodes vs psb0 faces */
+ if (this->m_tetras.size() > 0)
+ docollide.useFaceNormal = true;
+ else
+ docollide.useFaceNormal = false;
+ docollide.psb[0] = psb;
+ docollide.psb[1] = this;
+ docollide.psb[0]->m_ndbvt.collideTT(docollide.psb[0]->m_ndbvt.m_root,
+ docollide.psb[1]->m_fdbvt.m_root,
+ docollide);
+ }
+ else
+ {
+ if (psb->useSelfCollision())
+ {
+ btSoftColliders::CollideFF_DD docollide;
+ docollide.mrg = getCollisionShape()->getMargin() +
+ psb->getCollisionShape()->getMargin();
+ docollide.psb[0] = this;
+ docollide.psb[1] = psb;
+ if (this->m_tetras.size() > 0)
+ docollide.useFaceNormal = true;
+ else
+ docollide.useFaceNormal = false;
+ /* psb0 faces vs psb0 faces */
+ btDbvntNode* root = copyToDbvnt(this->m_fdbvt.m_root);
+ calculateNormalCone(root);
+ this->m_fdbvt.selfCollideT(root,docollide);
+ delete root;
+ }
+ }
+ }
+ }
+ break;
default:
{
}
@@ -3434,7 +3970,7 @@ const char* btSoftBody::serialize(void* dataBuffer, class btSerializer* serializ
for (int j = 0; j < 4; j++)
{
m_tetras[i].m_c0[j].serializeFloat(memPtr->m_c0[j]);
- memPtr->m_nodeIndices[j] = m_tetras[j].m_n[j] ? m_tetras[j].m_n[j] - &m_nodes[0] : -1;
+ memPtr->m_nodeIndices[j] = m_tetras[i].m_n[j] ? m_tetras[i].m_n[j] - &m_nodes[0] : -1;
}
memPtr->m_c1 = m_tetras[i].m_c1;
memPtr->m_c2 = m_tetras[i].m_c2;
@@ -3697,3 +4233,47 @@ const char* btSoftBody::serialize(void* dataBuffer, class btSerializer* serializ
return btSoftBodyDataName;
}
+
+void btSoftBody::updateDeactivation(btScalar timeStep)
+{
+ if ((getActivationState() == ISLAND_SLEEPING) || (getActivationState() == DISABLE_DEACTIVATION))
+ return;
+
+ if (m_maxSpeedSquared < m_sleepingThreshold * m_sleepingThreshold)
+ {
+ m_deactivationTime += timeStep;
+ }
+ else
+ {
+ m_deactivationTime = btScalar(0.);
+ setActivationState(0);
+ }
+}
+
+
+void btSoftBody::setZeroVelocity()
+{
+ for (int i = 0; i < m_nodes.size(); ++i)
+ {
+ m_nodes[i].m_v.setZero();
+ }
+}
+
+bool btSoftBody::wantsSleeping()
+{
+ if (getActivationState() == DISABLE_DEACTIVATION)
+ return false;
+
+ //disable deactivation
+ if (gDisableDeactivation || (gDeactivationTime == btScalar(0.)))
+ return false;
+
+ if ((getActivationState() == ISLAND_SLEEPING) || (getActivationState() == WANTS_DEACTIVATION))
+ return true;
+
+ if (m_deactivationTime > gDeactivationTime)
+ {
+ return true;
+ }
+ return false;
+}
diff --git a/thirdparty/bullet/BulletSoftBody/btSoftBody.h b/thirdparty/bullet/BulletSoftBody/btSoftBody.h
index 9b35b799d8..2b048c1118 100644
--- a/thirdparty/bullet/BulletSoftBody/btSoftBody.h
+++ b/thirdparty/bullet/BulletSoftBody/btSoftBody.h
@@ -20,13 +20,15 @@ subject to the following restrictions:
#include "LinearMath/btAlignedObjectArray.h"
#include "LinearMath/btTransform.h"
#include "LinearMath/btIDebugDraw.h"
+#include "LinearMath/btVector3.h"
#include "BulletDynamics/Dynamics/btRigidBody.h"
#include "BulletCollision/CollisionShapes/btConcaveShape.h"
#include "BulletCollision/CollisionDispatch/btCollisionCreateFunc.h"
#include "btSparseSDF.h"
#include "BulletCollision/BroadphaseCollision/btDbvt.h"
-
+#include "BulletDynamics/Featherstone/btMultiBodyLinkCollider.h"
+#include "BulletDynamics/Featherstone/btMultiBodyConstraint.h"
//#ifdef BT_USE_DOUBLE_PRECISION
//#define btRigidBodyData btRigidBodyDoubleData
//#define btRigidBodyDataName "btRigidBodyDoubleData"
@@ -159,11 +161,14 @@ public:
RVSmask = 0x000f, ///Rigid versus soft mask
SDF_RS = 0x0001, ///SDF based rigid vs soft
CL_RS = 0x0002, ///Cluster vs convex rigid vs soft
+ SDF_RD = 0x0003, ///DF based rigid vs deformable
+ SDF_RDF = 0x0004, ///DF based rigid vs deformable faces
- SVSmask = 0x0030, ///Rigid versus soft mask
+ SVSmask = 0x00F0, ///Rigid versus soft mask
VF_SS = 0x0010, ///Vertex vs face soft vs soft handling
CL_SS = 0x0020, ///Cluster vs cluster soft vs soft handling
CL_SELF = 0x0040, ///Cluster soft body self collision
+ VF_DD = 0x0050, ///Vertex vs face soft vs soft handling
/* presets */
Default = SDF_RS,
END
@@ -215,6 +220,7 @@ public:
const btCollisionObject* m_colObj; /* Rigid body */
btVector3 m_normal; /* Outward normal */
btScalar m_offset; /* Offset from origin */
+ btVector3 m_bary; /* Barycentric weights for faces */
};
/* sMedium */
@@ -249,14 +255,17 @@ public:
struct Node : Feature
{
btVector3 m_x; // Position
- btVector3 m_q; // Previous step position
+ btVector3 m_q; // Previous step position/Test position
btVector3 m_v; // Velocity
+ btVector3 m_vsplit; // Temporary Velocity in addintion to velocity used in split impulse
+ btVector3 m_vn; // Previous step velocity
btVector3 m_f; // Force accumulator
btVector3 m_n; // Normal
btScalar m_im; // 1/mass
btScalar m_area; // Area
btDbvtNode* m_leaf; // Leaf data
int m_battach : 1; // Attached
+ int index;
};
/* Link */
ATTRIBUTE_ALIGNED16(struct)
@@ -279,6 +288,8 @@ public:
btVector3 m_normal; // Normal
btScalar m_ra; // Rest area
btDbvtNode* m_leaf; // Leaf data
+ btVector4 m_pcontact; // barycentric weights of the persistent contact
+ int m_index;
};
/* Tetra */
struct Tetra : Feature
@@ -289,7 +300,20 @@ public:
btVector3 m_c0[4]; // gradients
btScalar m_c1; // (4*kVST)/(im0+im1+im2+im3)
btScalar m_c2; // m_c1/sum(|g0..3|^2)
+ btMatrix3x3 m_Dm_inverse; // rest Dm^-1
+ btMatrix3x3 m_F;
+ btScalar m_element_measure;
};
+
+ /* TetraScratch */
+ struct TetraScratch
+ {
+ btMatrix3x3 m_F; // deformation gradient F
+ btScalar m_trace; // trace of F^T * F
+ btScalar m_J; // det(F)
+ btMatrix3x3 m_cofF; // cofactor of F
+ };
+
/* RContact */
struct RContact
{
@@ -300,7 +324,67 @@ public:
btScalar m_c2; // ima*dt
btScalar m_c3; // Friction
btScalar m_c4; // Hardness
+
+ // jacobians and unit impulse responses for multibody
+ btMultiBodyJacobianData jacobianData_normal;
+ btMultiBodyJacobianData jacobianData_t1;
+ btMultiBodyJacobianData jacobianData_t2;
+ btVector3 t1;
+ btVector3 t2;
};
+
+ class DeformableRigidContact
+ {
+ public:
+ sCti m_cti; // Contact infos
+ btMatrix3x3 m_c0; // Impulse matrix
+ btVector3 m_c1; // Relative anchor
+ btScalar m_c2; // inverse mass of node/face
+ btScalar m_c3; // Friction
+ btScalar m_c4; // Hardness
+
+ // jacobians and unit impulse responses for multibody
+ btMultiBodyJacobianData jacobianData_normal;
+ btMultiBodyJacobianData jacobianData_t1;
+ btMultiBodyJacobianData jacobianData_t2;
+ btVector3 t1;
+ btVector3 t2;
+ };
+
+ class DeformableNodeRigidContact : public DeformableRigidContact
+ {
+ public:
+ Node* m_node; // Owner node
+ };
+
+ class DeformableNodeRigidAnchor : public DeformableNodeRigidContact
+ {
+ public:
+ btVector3 m_local; // Anchor position in body space
+ };
+
+ class DeformableFaceRigidContact : public DeformableRigidContact
+ {
+ public:
+ Face* m_face; // Owner face
+ btVector3 m_contactPoint; // Contact point
+ btVector3 m_bary; // Barycentric weights
+ btVector3 m_weights; // v_contactPoint * m_weights[i] = m_face->m_node[i]->m_v;
+ };
+
+ struct DeformableFaceNodeContact
+ {
+ Node* m_node; // Node
+ Face* m_face; // Face
+ btVector3 m_bary; // Barycentric weights
+ btVector3 m_weights; // v_contactPoint * m_weights[i] = m_face->m_node[i]->m_v;
+ btVector3 m_normal; // Normal
+ btScalar m_margin; // Margin
+ btScalar m_friction; // Friction
+ btScalar m_imf; // inverse mass of the face at contact point
+ btScalar m_c0; // scale of the impulse matrix;
+ };
+
/* SContact */
struct SContact
{
@@ -627,6 +711,8 @@ public:
tVSolverArray m_vsequence; // Velocity solvers sequence
tPSolverArray m_psequence; // Position solvers sequence
tPSolverArray m_dsequence; // Drift solvers sequence
+ btScalar drag; // deformable air drag
+ btScalar m_maxStress; // Maximum principle first Piola stress
};
/* SolverState */
struct SolverState
@@ -689,11 +775,19 @@ public:
btSoftBodyWorldInfo* m_worldInfo; // World info
tNoteArray m_notes; // Notes
tNodeArray m_nodes; // Nodes
+ tNodeArray m_renderNodes; // Nodes
tLinkArray m_links; // Links
tFaceArray m_faces; // Faces
+ tFaceArray m_renderFaces; // Faces
tTetraArray m_tetras; // Tetras
+ btAlignedObjectArray<TetraScratch> m_tetraScratches;
+ btAlignedObjectArray<TetraScratch> m_tetraScratchesTn;
tAnchorArray m_anchors; // Anchors
+ btAlignedObjectArray<DeformableNodeRigidAnchor> m_deformableAnchors;
tRContactArray m_rcontacts; // Rigid contacts
+ btAlignedObjectArray<DeformableNodeRigidContact> m_nodeRigidContacts;
+ btAlignedObjectArray<DeformableFaceNodeContact> m_faceNodeContacts;
+ btAlignedObjectArray<DeformableFaceRigidContact> m_faceRigidContacts;
tSContactArray m_scontacts; // Soft contacts
tJointArray m_joints; // Joints
tMaterialArray m_materials; // Materials
@@ -704,6 +798,15 @@ public:
btDbvt m_fdbvt; // Faces tree
btDbvt m_cdbvt; // Clusters tree
tClusterArray m_clusters; // Clusters
+ btScalar m_dampingCoefficient; // Damping Coefficient
+ btScalar m_sleepingThreshold;
+ btScalar m_maxSpeedSquared;
+ bool m_useFaceContact;
+ btAlignedObjectArray<btVector3> m_quads; // quadrature points for collision detection
+
+ btAlignedObjectArray<btVector4> m_renderNodesInterpolationWeights;
+ btAlignedObjectArray<btAlignedObjectArray<const btSoftBody::Node*> > m_renderNodesParents;
+ bool m_useSelfCollision;
btAlignedObjectArray<bool> m_clusterConnectivity; //cluster connectivity, for self-collision
@@ -735,6 +838,16 @@ public:
{
return m_worldInfo;
}
+
+ void setDampingCoefficient(btScalar damping_coeff)
+ {
+ m_dampingCoefficient = damping_coeff;
+ }
+
+ void setUseFaceContact(bool useFaceContact)
+ {
+ m_useFaceContact = false;
+ }
///@todo: avoid internal softbody shape hack and move collision code to collision library
virtual void setCollisionShape(btCollisionShape* collisionShape)
@@ -795,7 +908,9 @@ public:
Material* mat = 0);
/* Append anchor */
- void appendAnchor(int node,
+ void appendDeformableAnchor(int node, btRigidBody* body);
+ void appendDeformableAnchor(int node, btMultiBodyLinkCollider* link);
+ void appendAnchor(int node,
btRigidBody* body, bool disableCollisionBetweenLinkedBodies = false, btScalar influence = 1);
void appendAnchor(int node, btRigidBody* body, const btVector3& localPivot, bool disableCollisionBetweenLinkedBodies = false, btScalar influence = 1);
/* Append linear joint */
@@ -862,6 +977,16 @@ public:
/* Return the volume */
btScalar getVolume() const;
/* Cluster count */
+ btVector3 getCenterOfMass() const
+ {
+ btVector3 com(0, 0, 0);
+ for (int i = 0; i < m_nodes.size(); i++)
+ {
+ com += (m_nodes[i].m_x * this->getMass(i));
+ }
+ com /= this->getTotalMass();
+ return com;
+ }
int clusterCount() const;
/* Cluster center of mass */
static btVector3 clusterCom(const Cluster* cluster);
@@ -915,6 +1040,11 @@ public:
/* defaultCollisionHandlers */
void defaultCollisionHandler(const btCollisionObjectWrapper* pcoWrap);
void defaultCollisionHandler(btSoftBody* psb);
+ void setSelfCollision(bool useSelfCollision);
+ bool useSelfCollision();
+ void updateDeactivation(btScalar timeStep);
+ void setZeroVelocity();
+ bool wantsSleeping();
//
// Functionality to deal with new accelerated solvers.
@@ -991,7 +1121,9 @@ public:
btScalar& mint, eFeature::_& feature, int& index, bool bcountonly) const;
void initializeFaceTree();
btVector3 evaluateCom() const;
- bool checkContact(const btCollisionObjectWrapper* colObjWrap, const btVector3& x, btScalar margin, btSoftBody::sCti& cti) const;
+ bool checkDeformableContact(const btCollisionObjectWrapper* colObjWrap, const btVector3& x, btScalar margin, btSoftBody::sCti& cti, bool predict = false) const;
+ bool checkDeformableFaceContact(const btCollisionObjectWrapper* colObjWrap, Face& f, btVector3& contact_point, btVector3& bary, btScalar margin, btSoftBody::sCti& cti, bool predict = false) const;
+ bool checkContact(const btCollisionObjectWrapper* colObjWrap, const btVector3& x, btScalar margin, btSoftBody::sCti& cti) const;
void updateNormals();
void updateBounds();
void updatePose();
@@ -1005,7 +1137,14 @@ public:
void solveClusters(btScalar sor);
void applyClusters(bool drift);
void dampClusters();
+ void setSpringStiffness(btScalar k);
+ void initializeDmInverse();
+ void updateDeformation();
+ void advanceDeformation();
void applyForces();
+ void setMaxStress(btScalar maxStress);
+ void interpolateRenderMesh();
+ void setCollisionQuadrature(int N);
static void PSolve_Anchors(btSoftBody* psb, btScalar kst, btScalar ti);
static void PSolve_RContacts(btSoftBody* psb, btScalar kst, btScalar ti);
static void PSolve_SContacts(btSoftBody* psb, btScalar, btScalar ti);
@@ -1015,11 +1154,9 @@ public:
static vsolver_t getSolver(eVSolver::_ solver);
virtual int calculateSerializeBufferSize() const;
-
+
///fills the dataBuffer and returns the struct name (and 0 on failure)
virtual const char* serialize(void* dataBuffer, class btSerializer* serializer) const;
-
- //virtual void serializeSingleObject(class btSerializer* serializer) const;
};
#endif //_BT_SOFT_BODY_H
diff --git a/thirdparty/bullet/BulletSoftBody/btSoftBodyHelpers.cpp b/thirdparty/bullet/BulletSoftBody/btSoftBodyHelpers.cpp
index d0a9921d89..649d6f58cf 100644
--- a/thirdparty/bullet/BulletSoftBody/btSoftBodyHelpers.cpp
+++ b/thirdparty/bullet/BulletSoftBody/btSoftBodyHelpers.cpp
@@ -16,12 +16,17 @@ subject to the following restrictions:
#include "btSoftBodyInternals.h"
#include <stdio.h>
+#include <string>
+#include <iostream>
+#include <sstream>
#include <string.h>
+#include <algorithm>
#include "btSoftBodyHelpers.h"
#include "LinearMath/btConvexHull.h"
#include "LinearMath/btConvexHullComputer.h"
+#include <map>
+#include <vector>
-//
static void drawVertex(btIDebugDraw* idraw,
const btVector3& x, btScalar s, const btVector3& c)
{
@@ -721,7 +726,8 @@ btSoftBody* btSoftBodyHelpers::CreatePatch(btSoftBodyWorldInfo& worldInfo, const
int resx,
int resy,
int fixeds,
- bool gendiags)
+ bool gendiags,
+ btScalar perturbation)
{
#define IDX(_x_, _y_) ((_y_)*rx + (_x_))
/* Create nodes */
@@ -741,7 +747,13 @@ btSoftBody* btSoftBodyHelpers::CreatePatch(btSoftBodyWorldInfo& worldInfo, const
for (int ix = 0; ix < rx; ++ix)
{
const btScalar tx = ix / (btScalar)(rx - 1);
- x[IDX(ix, iy)] = lerp(py0, py1, tx);
+ btScalar pert = perturbation * btScalar(rand())/RAND_MAX;
+ btVector3 temp1 = py1;
+ temp1.setY(py1.getY() + pert);
+ btVector3 temp = py0;
+ pert = perturbation * btScalar(rand())/RAND_MAX;
+ temp.setY(py0.getY() + pert);
+ x[IDX(ix, iy)] = lerp(temp, temp1, tx);
m[IDX(ix, iy)] = 1;
}
}
@@ -1221,9 +1233,314 @@ if(face&&face[0])
}
}
}
+ psb->initializeDmInverse();
+ psb->m_tetraScratches.resize(psb->m_tetras.size());
+ psb->m_tetraScratchesTn.resize(psb->m_tetras.size());
printf("Nodes: %u\r\n", psb->m_nodes.size());
printf("Links: %u\r\n", psb->m_links.size());
printf("Faces: %u\r\n", psb->m_faces.size());
printf("Tetras: %u\r\n", psb->m_tetras.size());
return (psb);
}
+
+btSoftBody* btSoftBodyHelpers::CreateFromVtkFile(btSoftBodyWorldInfo& worldInfo, const char* vtk_file)
+{
+ std::ifstream fs;
+ fs.open(vtk_file);
+ btAssert(fs);
+
+ typedef btAlignedObjectArray<int> Index;
+ std::string line;
+ btAlignedObjectArray<btVector3> X;
+ btVector3 position;
+ btAlignedObjectArray<Index> indices;
+ bool reading_points = false;
+ bool reading_tets = false;
+ size_t n_points = 0;
+ size_t n_tets = 0;
+ size_t x_count = 0;
+ size_t indices_count = 0;
+ while (std::getline(fs, line))
+ {
+ std::stringstream ss(line);
+ if (line.size() == (size_t)(0))
+ {
+ }
+ else if (line.substr(0, 6) == "POINTS")
+ {
+ reading_points = true;
+ reading_tets = false;
+ ss.ignore(128, ' '); // ignore "POINTS"
+ ss >> n_points;
+ X.resize(n_points);
+ }
+ else if (line.substr(0, 5) == "CELLS")
+ {
+ reading_points = false;
+ reading_tets = true;
+ ss.ignore(128, ' '); // ignore "CELLS"
+ ss >> n_tets;
+ indices.resize(n_tets);
+ }
+ else if (line.substr(0, 10) == "CELL_TYPES")
+ {
+ reading_points = false;
+ reading_tets = false;
+ }
+ else if (reading_points)
+ {
+ btScalar p;
+ ss >> p;
+ position.setX(p);
+ ss >> p;
+ position.setY(p);
+ ss >> p;
+ position.setZ(p);
+ X[x_count++] = position;
+ }
+ else if (reading_tets)
+ {
+ ss.ignore(128, ' '); // ignore "4"
+ Index tet;
+ tet.resize(4);
+ for (size_t i = 0; i < 4; i++)
+ {
+ ss >> tet[i];
+ }
+ indices[indices_count++] = tet;
+ }
+ }
+ btSoftBody* psb = new btSoftBody(&worldInfo, n_points, &X[0], 0);
+
+ for (int i = 0; i < n_tets; ++i)
+ {
+ const Index& ni = indices[i];
+ psb->appendTetra(ni[0], ni[1], ni[2], ni[3]);
+ {
+ psb->appendLink(ni[0], ni[1], 0, true);
+ psb->appendLink(ni[1], ni[2], 0, true);
+ psb->appendLink(ni[2], ni[0], 0, true);
+ psb->appendLink(ni[0], ni[3], 0, true);
+ psb->appendLink(ni[1], ni[3], 0, true);
+ psb->appendLink(ni[2], ni[3], 0, true);
+ }
+ }
+
+
+ generateBoundaryFaces(psb);
+ psb->initializeDmInverse();
+ psb->m_tetraScratches.resize(psb->m_tetras.size());
+ psb->m_tetraScratchesTn.resize(psb->m_tetras.size());
+ printf("Nodes: %u\r\n", psb->m_nodes.size());
+ printf("Links: %u\r\n", psb->m_links.size());
+ printf("Faces: %u\r\n", psb->m_faces.size());
+ printf("Tetras: %u\r\n", psb->m_tetras.size());
+
+ fs.close();
+ return psb;
+}
+
+void btSoftBodyHelpers::generateBoundaryFaces(btSoftBody* psb)
+{
+ int counter = 0;
+ for (int i = 0; i < psb->m_nodes.size(); ++i)
+ {
+ psb->m_nodes[i].index = counter++;
+ }
+ typedef btAlignedObjectArray<int> Index;
+ btAlignedObjectArray<Index> indices;
+ indices.resize(psb->m_tetras.size());
+ for (int i = 0; i < indices.size(); ++i)
+ {
+ Index index;
+ index.push_back(psb->m_tetras[i].m_n[0]->index);
+ index.push_back(psb->m_tetras[i].m_n[1]->index);
+ index.push_back(psb->m_tetras[i].m_n[2]->index);
+ index.push_back(psb->m_tetras[i].m_n[3]->index);
+ indices[i] = index;
+ }
+
+ std::map<std::vector<int>, std::vector<int> > dict;
+ for (int i = 0; i < indices.size(); ++i)
+ {
+ for (int j = 0; j < 4; ++j)
+ {
+ std::vector<int> f;
+ if (j == 0)
+ {
+ f.push_back(indices[i][1]);
+ f.push_back(indices[i][0]);
+ f.push_back(indices[i][2]);
+ }
+ if (j == 1)
+ {
+ f.push_back(indices[i][3]);
+ f.push_back(indices[i][0]);
+ f.push_back(indices[i][1]);
+ }
+ if (j == 2)
+ {
+ f.push_back(indices[i][3]);
+ f.push_back(indices[i][1]);
+ f.push_back(indices[i][2]);
+ }
+ if (j == 3)
+ {
+ f.push_back(indices[i][2]);
+ f.push_back(indices[i][0]);
+ f.push_back(indices[i][3]);
+ }
+ std::vector<int> f_sorted = f;
+ std::sort(f_sorted.begin(), f_sorted.end());
+ if (dict.find(f_sorted) != dict.end())
+ {
+ dict.erase(f_sorted);
+ }
+ else
+ {
+ dict.insert(std::make_pair(f_sorted, f));
+ }
+ }
+ }
+
+ for (std::map<std::vector<int>, std::vector<int> >::iterator it = dict.begin(); it != dict.end(); ++it)
+ {
+ std::vector<int> f = it->second;
+ psb->appendFace(f[0], f[1], f[2]);
+ }
+}
+
+void btSoftBodyHelpers::writeObj(const char* filename, const btSoftBody* psb)
+{
+ std::ofstream fs;
+ fs.open(filename);
+ btAssert(fs);
+ for (int i = 0; i < psb->m_nodes.size(); ++i)
+ {
+ fs << "v";
+ for (int d = 0; d < 3; d++)
+ {
+ fs << " " << psb->m_nodes[i].m_x[d];
+ }
+ fs << "\n";
+ }
+
+ for (int i = 0; i < psb->m_faces.size(); ++i)
+ {
+ fs << "f";
+ for (int n = 0; n < 3; n++)
+ {
+ fs << " " << psb->m_faces[i].m_n[n]->index + 1;
+ }
+ fs << "\n";
+ }
+ fs.close();
+}
+
+void btSoftBodyHelpers::duplicateFaces(const char* filename, const btSoftBody* psb)
+{
+ std::ifstream fs_read;
+ fs_read.open(filename);
+ std::string line;
+ btVector3 pos;
+ btAlignedObjectArray<btAlignedObjectArray<int> > additional_faces;
+ while (std::getline(fs_read, line))
+ {
+ std::stringstream ss(line);
+ if (line[0] == 'v')
+ {
+ }
+ else if (line[0] == 'f')
+ {
+ ss.ignore();
+ int id0, id1, id2;
+ ss >> id0;
+ ss >> id1;
+ ss >> id2;
+ btAlignedObjectArray<int> new_face;
+ new_face.push_back(id1);
+ new_face.push_back(id0);
+ new_face.push_back(id2);
+ additional_faces.push_back(new_face);
+ }
+ }
+ fs_read.close();
+
+ std::ofstream fs_write;
+ fs_write.open(filename, std::ios_base::app);
+ for (int i = 0; i < additional_faces.size(); ++i)
+ {
+ fs_write << "f";
+ for (int n = 0; n < 3; n++)
+ {
+ fs_write << " " << additional_faces[i][n];
+ }
+ fs_write << "\n";
+ }
+ fs_write.close();
+}
+
+// Given a simplex with vertices a,b,c,d, find the barycentric weights of p in this simplex
+void btSoftBodyHelpers::getBarycentricWeights(const btVector3& a, const btVector3& b, const btVector3& c, const btVector3& d, const btVector3& p, btVector4& bary)
+{
+ btVector3 vap = p - a;
+ btVector3 vbp = p - b;
+
+ btVector3 vab = b - a;
+ btVector3 vac = c - a;
+ btVector3 vad = d - a;
+
+ btVector3 vbc = c - b;
+ btVector3 vbd = d - b;
+ btScalar va6 = (vbp.cross(vbd)).dot(vbc);
+ btScalar vb6 = (vap.cross(vac)).dot(vad);
+ btScalar vc6 = (vap.cross(vad)).dot(vab);
+ btScalar vd6 = (vap.cross(vab)).dot(vac);
+ btScalar v6 = btScalar(1) / (vab.cross(vac).dot(vad));
+ bary = btVector4(va6*v6, vb6*v6, vc6*v6, vd6*v6);
+}
+
+// Iterate through all render nodes to find the simulation tetrahedron that contains the render node and record the barycentric weights
+// If the node is not inside any tetrahedron, assign it to the tetrahedron in which the node has the least negative barycentric weight
+void btSoftBodyHelpers::interpolateBarycentricWeights(btSoftBody* psb)
+{
+ psb->m_renderNodesInterpolationWeights.resize(psb->m_renderNodes.size());
+ psb->m_renderNodesParents.resize(psb->m_renderNodes.size());
+ for (int i = 0; i < psb->m_renderNodes.size(); ++i)
+ {
+ const btVector3& p = psb->m_renderNodes[i].m_x;
+ btVector4 bary;
+ btVector4 optimal_bary;
+ btScalar min_bary_weight = -1e3;
+ btAlignedObjectArray<const btSoftBody::Node*> optimal_parents;
+ bool found = false;
+ for (int j = 0; j < psb->m_tetras.size(); ++j)
+ {
+ const btSoftBody::Tetra& t = psb->m_tetras[j];
+ getBarycentricWeights(t.m_n[0]->m_x, t.m_n[1]->m_x, t.m_n[2]->m_x, t.m_n[3]->m_x, p, bary);
+ btScalar new_min_bary_weight = bary[0];
+ for (int k = 1; k < 4; ++k)
+ {
+ new_min_bary_weight = btMin(new_min_bary_weight, bary[k]);
+ }
+ if (new_min_bary_weight > min_bary_weight)
+ {
+ btAlignedObjectArray<const btSoftBody::Node*> parents;
+ parents.push_back(t.m_n[0]);
+ parents.push_back(t.m_n[1]);
+ parents.push_back(t.m_n[2]);
+ parents.push_back(t.m_n[3]);
+ optimal_parents = parents;
+ optimal_bary = bary;
+ min_bary_weight = new_min_bary_weight;
+ // stop searching if p is inside the tetrahedron at hand
+ if (bary[0]>=0. && bary[1]>=0. && bary[2]>=0. && bary[3]>=0.)
+ {
+ break;
+ }
+ }
+ }
+ psb->m_renderNodesInterpolationWeights[i] = optimal_bary;
+ psb->m_renderNodesParents[i] = optimal_parents;
+ }
+}
diff --git a/thirdparty/bullet/BulletSoftBody/btSoftBodyHelpers.h b/thirdparty/bullet/BulletSoftBody/btSoftBodyHelpers.h
index e433558c18..b20f2f6d62 100644
--- a/thirdparty/bullet/BulletSoftBody/btSoftBodyHelpers.h
+++ b/thirdparty/bullet/BulletSoftBody/btSoftBodyHelpers.h
@@ -17,7 +17,8 @@ subject to the following restrictions:
#define BT_SOFT_BODY_HELPERS_H
#include "btSoftBody.h"
-
+#include <fstream>
+#include <string>
//
// Helpers
//
@@ -91,7 +92,8 @@ struct btSoftBodyHelpers
int resx,
int resy,
int fixeds,
- bool gendiags);
+ bool gendiags,
+ btScalar perturbation = 0.);
/* Create a patch with UV Texture Coordinates */
static btSoftBody* CreatePatchUV(btSoftBodyWorldInfo& worldInfo,
const btVector3& corner00,
@@ -140,7 +142,17 @@ struct btSoftBodyHelpers
bool bfacelinks,
bool btetralinks,
bool bfacesfromtetras);
+ static btSoftBody* CreateFromVtkFile(btSoftBodyWorldInfo& worldInfo, const char* vtk_file);
+ static void writeObj(const char* file, const btSoftBody* psb);
+
+ static void getBarycentricWeights(const btVector3& a, const btVector3& b, const btVector3& c, const btVector3& d, const btVector3& p, btVector4& bary);
+
+ static void interpolateBarycentricWeights(btSoftBody* psb);
+
+ static void generateBoundaryFaces(btSoftBody* psb);
+
+ static void duplicateFaces(const char* filename, const btSoftBody* psb);
/// Sort the list of links to move link calculations that are dependent upon earlier
/// ones as far as possible away from the calculation of those values
/// This tends to make adjacent loop iterations not dependent upon one another,
diff --git a/thirdparty/bullet/BulletSoftBody/btSoftBodyInternals.h b/thirdparty/bullet/BulletSoftBody/btSoftBodyInternals.h
index 7efe514f38..cde4746d58 100644
--- a/thirdparty/bullet/BulletSoftBody/btSoftBodyInternals.h
+++ b/thirdparty/bullet/BulletSoftBody/btSoftBodyInternals.h
@@ -25,7 +25,43 @@ subject to the following restrictions:
#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h"
#include "BulletCollision/CollisionShapes/btConvexInternalShape.h"
#include "BulletCollision/NarrowPhaseCollision/btGjkEpa2.h"
+#include "BulletDynamics/Featherstone/btMultiBodyLinkCollider.h"
+#include "BulletDynamics/Featherstone/btMultiBodyConstraint.h"
#include <string.h> //for memset
+#include <cmath>
+
+// Given a multibody link, a contact point and a contact direction, fill in the jacobian data needed to calculate the velocity change given an impulse in the contact direction
+static void findJacobian(const btMultiBodyLinkCollider* multibodyLinkCol,
+ btMultiBodyJacobianData& jacobianData,
+ const btVector3& contact_point,
+ const btVector3& dir)
+{
+ const int ndof = multibodyLinkCol->m_multiBody->getNumDofs() + 6;
+ jacobianData.m_jacobians.resize(ndof);
+ jacobianData.m_deltaVelocitiesUnitImpulse.resize(ndof);
+ btScalar* jac = &jacobianData.m_jacobians[0];
+
+ multibodyLinkCol->m_multiBody->fillContactJacobianMultiDof(multibodyLinkCol->m_link, contact_point, dir, jac, jacobianData.scratch_r, jacobianData.scratch_v, jacobianData.scratch_m);
+ multibodyLinkCol->m_multiBody->calcAccelerationDeltasMultiDof(&jacobianData.m_jacobians[0], &jacobianData.m_deltaVelocitiesUnitImpulse[0], jacobianData.scratch_r, jacobianData.scratch_v);
+}
+static btVector3 generateUnitOrthogonalVector(const btVector3& u)
+{
+ btScalar ux = u.getX();
+ btScalar uy = u.getY();
+ btScalar uz = u.getZ();
+ btScalar ax = std::abs(ux);
+ btScalar ay = std::abs(uy);
+ btScalar az = std::abs(uz);
+ btVector3 v;
+ if (ax <= ay && ax <= az)
+ v = btVector3(0, -uz, uy);
+ else if (ay <= ax && ay <= az)
+ v = btVector3(-uz, 0, ux);
+ else
+ v = btVector3(-uy, ux, 0);
+ v.normalize();
+ return v;
+}
//
// btSymMatrix
//
@@ -298,6 +334,46 @@ static inline btMatrix3x3 Diagonal(btScalar x)
m[2] = btVector3(0, 0, x);
return (m);
}
+
+static inline btMatrix3x3 Diagonal(const btVector3& v)
+{
+ btMatrix3x3 m;
+ m[0] = btVector3(v.getX(), 0, 0);
+ m[1] = btVector3(0, v.getY(), 0);
+ m[2] = btVector3(0, 0, v.getZ());
+ return (m);
+}
+
+static inline btScalar Dot(const btScalar* a,const btScalar* b, int ndof)
+{
+ btScalar result = 0;
+ for (int i = 0; i < ndof; ++i)
+ result += a[i] * b[i];
+ return result;
+}
+
+static inline btMatrix3x3 OuterProduct(const btScalar* v1,const btScalar* v2,const btScalar* v3,
+ const btScalar* u1, const btScalar* u2, const btScalar* u3, int ndof)
+{
+ btMatrix3x3 m;
+ btScalar a11 = Dot(v1,u1,ndof);
+ btScalar a12 = Dot(v1,u2,ndof);
+ btScalar a13 = Dot(v1,u3,ndof);
+
+ btScalar a21 = Dot(v2,u1,ndof);
+ btScalar a22 = Dot(v2,u2,ndof);
+ btScalar a23 = Dot(v2,u3,ndof);
+
+ btScalar a31 = Dot(v3,u1,ndof);
+ btScalar a32 = Dot(v3,u2,ndof);
+ btScalar a33 = Dot(v3,u3,ndof);
+ m[0] = btVector3(a11, a12, a13);
+ m[1] = btVector3(a21, a22, a23);
+ m[2] = btVector3(a31, a32, a33);
+ return (m);
+}
+
+
//
static inline btMatrix3x3 Add(const btMatrix3x3& a,
const btMatrix3x3& b)
@@ -428,6 +504,77 @@ static inline void ProjectOrigin(const btVector3& a,
}
//
+static inline bool rayIntersectsTriangle(const btVector3& origin, const btVector3& dir, const btVector3& v0, const btVector3& v1, const btVector3& v2, btScalar& t)
+{
+ btScalar a, f, u, v;
+
+ btVector3 e1 = v1 - v0;
+ btVector3 e2 = v2 - v0;
+ btVector3 h = dir.cross(e2);
+ a = e1.dot(h);
+
+ if (a > -0.00001 && a < 0.00001)
+ return (false);
+
+ f = btScalar(1) / a;
+ btVector3 s = origin - v0;
+ u = f * s.dot(h);
+
+ if (u < 0.0 || u > 1.0)
+ return (false);
+
+ btVector3 q = s.cross(e1);
+ v = f * dir.dot(q);
+ if (v < 0.0 || u + v > 1.0)
+ return (false);
+ // at this stage we can compute t to find out where
+ // the intersection point is on the line
+ t = f * e2.dot(q);
+ if (t > 0) // ray intersection
+ return (true);
+ else // this means that there is a line intersection
+ // but not a ray intersection
+ return (false);
+}
+
+static inline bool lineIntersectsTriangle(const btVector3& rayStart, const btVector3& rayEnd, const btVector3& p1, const btVector3& p2, const btVector3& p3, btVector3& sect, btVector3& normal)
+{
+ btVector3 dir = rayEnd - rayStart;
+ btScalar dir_norm = dir.norm();
+ if (dir_norm < SIMD_EPSILON)
+ return false;
+ dir.normalize();
+
+ btScalar t;
+
+ bool ret = rayIntersectsTriangle(rayStart, dir, p1, p2, p3, t);
+
+ if (ret)
+ {
+ if (t <= dir_norm)
+ {
+ sect = rayStart + dir * t;
+ }
+ else
+ {
+ ret = false;
+ }
+ }
+
+ if (ret)
+ {
+ btVector3 n = (p3-p1).cross(p2-p1);
+ n.safeNormalize();
+ if (n.dot(dir) < 0)
+ normal = n;
+ else
+ normal = -n;
+ }
+ return ret;
+}
+
+
+//
template <typename T>
static inline T BaryEval(const T& a,
const T& b,
@@ -854,10 +1001,62 @@ struct btSoftColliders
psa->m_cdbvt.collideTT(psa->m_cdbvt.m_root, psb->m_cdbvt.m_root, *this);
}
};
+ //
+ // CollideSDF_RS
+ //
+ struct CollideSDF_RS : btDbvt::ICollide
+ {
+ void Process(const btDbvtNode* leaf)
+ {
+ btSoftBody::Node* node = (btSoftBody::Node*)leaf->data;
+ DoNode(*node);
+ }
+ void DoNode(btSoftBody::Node& n) const
+ {
+ const btScalar m = n.m_im > 0 ? dynmargin : stamargin;
+ btSoftBody::RContact c;
+
+ if ((!n.m_battach) &&
+ psb->checkContact(m_colObj1Wrap, n.m_x, m, c.m_cti))
+ {
+ const btScalar ima = n.m_im;
+ const btScalar imb = m_rigidBody ? m_rigidBody->getInvMass() : 0.f;
+ const btScalar ms = ima + imb;
+ if (ms > 0)
+ {
+ const btTransform& wtr = m_rigidBody ? m_rigidBody->getWorldTransform() : m_colObj1Wrap->getCollisionObject()->getWorldTransform();
+ static const btMatrix3x3 iwiStatic(0, 0, 0, 0, 0, 0, 0, 0, 0);
+ const btMatrix3x3& iwi = m_rigidBody ? m_rigidBody->getInvInertiaTensorWorld() : iwiStatic;
+ const btVector3 ra = n.m_x - wtr.getOrigin();
+ const btVector3 va = m_rigidBody ? m_rigidBody->getVelocityInLocalPoint(ra) * psb->m_sst.sdt : btVector3(0, 0, 0);
+ const btVector3 vb = n.m_x - n.m_q;
+ const btVector3 vr = vb - va;
+ const btScalar dn = btDot(vr, c.m_cti.m_normal);
+ const btVector3 fv = vr - c.m_cti.m_normal * dn;
+ const btScalar fc = psb->m_cfg.kDF * m_colObj1Wrap->getCollisionObject()->getFriction();
+ c.m_node = &n;
+ c.m_c0 = ImpulseMatrix(psb->m_sst.sdt, ima, imb, iwi, ra);
+ c.m_c1 = ra;
+ c.m_c2 = ima * psb->m_sst.sdt;
+ c.m_c3 = fv.length2() < (dn * fc * dn * fc) ? 0 : 1 - fc;
+ c.m_c4 = m_colObj1Wrap->getCollisionObject()->isStaticOrKinematicObject() ? psb->m_cfg.kKHR : psb->m_cfg.kCHR;
+ psb->m_rcontacts.push_back(c);
+ if (m_rigidBody)
+ m_rigidBody->activate();
+ }
+ }
+ }
+ btSoftBody* psb;
+ const btCollisionObjectWrapper* m_colObj1Wrap;
+ btRigidBody* m_rigidBody;
+ btScalar dynmargin;
+ btScalar stamargin;
+ };
+
//
- // CollideSDF_RS
+ // CollideSDF_RD
//
- struct CollideSDF_RS : btDbvt::ICollide
+ struct CollideSDF_RD : btDbvt::ICollide
{
void Process(const btDbvtNode* leaf)
{
@@ -867,36 +1066,75 @@ struct btSoftColliders
void DoNode(btSoftBody::Node& n) const
{
const btScalar m = n.m_im > 0 ? dynmargin : stamargin;
- btSoftBody::RContact c;
+ btSoftBody::DeformableNodeRigidContact c;
- if ((!n.m_battach) &&
- psb->checkContact(m_colObj1Wrap, n.m_x, m, c.m_cti))
- {
- const btScalar ima = n.m_im;
- const btScalar imb = m_rigidBody ? m_rigidBody->getInvMass() : 0.f;
- const btScalar ms = ima + imb;
- if (ms > 0)
- {
- const btTransform& wtr = m_rigidBody ? m_rigidBody->getWorldTransform() : m_colObj1Wrap->getCollisionObject()->getWorldTransform();
- static const btMatrix3x3 iwiStatic(0, 0, 0, 0, 0, 0, 0, 0, 0);
- const btMatrix3x3& iwi = m_rigidBody ? m_rigidBody->getInvInertiaTensorWorld() : iwiStatic;
- const btVector3 ra = n.m_x - wtr.getOrigin();
- const btVector3 va = m_rigidBody ? m_rigidBody->getVelocityInLocalPoint(ra) * psb->m_sst.sdt : btVector3(0, 0, 0);
- const btVector3 vb = n.m_x - n.m_q;
- const btVector3 vr = vb - va;
- const btScalar dn = btDot(vr, c.m_cti.m_normal);
- const btVector3 fv = vr - c.m_cti.m_normal * dn;
- const btScalar fc = psb->m_cfg.kDF * m_colObj1Wrap->getCollisionObject()->getFriction();
- c.m_node = &n;
- c.m_c0 = ImpulseMatrix(psb->m_sst.sdt, ima, imb, iwi, ra);
- c.m_c1 = ra;
- c.m_c2 = ima * psb->m_sst.sdt;
- c.m_c3 = fv.length2() < (dn * fc * dn * fc) ? 0 : 1 - fc;
- c.m_c4 = m_colObj1Wrap->getCollisionObject()->isStaticOrKinematicObject() ? psb->m_cfg.kKHR : psb->m_cfg.kCHR;
- psb->m_rcontacts.push_back(c);
- if (m_rigidBody)
- m_rigidBody->activate();
- }
+ if (!n.m_battach)
+ {
+ // check for collision at x_{n+1}^* as well at x_n
+ if (psb->checkDeformableContact(m_colObj1Wrap, n.m_x, m, c.m_cti, /*predict = */ true) || psb->checkDeformableContact(m_colObj1Wrap, n.m_q, m, c.m_cti, /*predict = */ true))
+ {
+ const btScalar ima = n.m_im;
+ // todo: collision between multibody and fixed deformable node will be missed.
+ const btScalar imb = m_rigidBody ? m_rigidBody->getInvMass() : 0.f;
+ const btScalar ms = ima + imb;
+ if (ms > 0)
+ {
+ // resolve contact at x_n
+ psb->checkDeformableContact(m_colObj1Wrap, n.m_x, m, c.m_cti, /*predict = */ false);
+ btSoftBody::sCti& cti = c.m_cti;
+ c.m_node = &n;
+ const btScalar fc = psb->m_cfg.kDF * m_colObj1Wrap->getCollisionObject()->getFriction();
+ c.m_c2 = ima;
+ c.m_c3 = fc;
+ c.m_c4 = m_colObj1Wrap->getCollisionObject()->isStaticOrKinematicObject() ? psb->m_cfg.kKHR : psb->m_cfg.kCHR;
+
+ if (cti.m_colObj->getInternalType() == btCollisionObject::CO_RIGID_BODY)
+ {
+ const btTransform& wtr = m_rigidBody ? m_rigidBody->getWorldTransform() : m_colObj1Wrap->getCollisionObject()->getWorldTransform();
+ static const btMatrix3x3 iwiStatic(0, 0, 0, 0, 0, 0, 0, 0, 0);
+ const btMatrix3x3& iwi = m_rigidBody ? m_rigidBody->getInvInertiaTensorWorld() : iwiStatic;
+ const btVector3 ra = n.m_x - wtr.getOrigin();
+
+ c.m_c0 = ImpulseMatrix(1, ima, imb, iwi, ra);
+ c.m_c1 = ra;
+ }
+ else if (cti.m_colObj->getInternalType() == btCollisionObject::CO_FEATHERSTONE_LINK)
+ {
+ btMultiBodyLinkCollider* multibodyLinkCol = (btMultiBodyLinkCollider*)btMultiBodyLinkCollider::upcast(cti.m_colObj);
+ if (multibodyLinkCol)
+ {
+ btVector3 normal = cti.m_normal;
+ btVector3 t1 = generateUnitOrthogonalVector(normal);
+ btVector3 t2 = btCross(normal, t1);
+ btMultiBodyJacobianData jacobianData_normal, jacobianData_t1, jacobianData_t2;
+ findJacobian(multibodyLinkCol, jacobianData_normal, c.m_node->m_x, normal);
+ findJacobian(multibodyLinkCol, jacobianData_t1, c.m_node->m_x, t1);
+ findJacobian(multibodyLinkCol, jacobianData_t2, c.m_node->m_x, t2);
+
+ btScalar* J_n = &jacobianData_normal.m_jacobians[0];
+ btScalar* J_t1 = &jacobianData_t1.m_jacobians[0];
+ btScalar* J_t2 = &jacobianData_t2.m_jacobians[0];
+
+ btScalar* u_n = &jacobianData_normal.m_deltaVelocitiesUnitImpulse[0];
+ btScalar* u_t1 = &jacobianData_t1.m_deltaVelocitiesUnitImpulse[0];
+ btScalar* u_t2 = &jacobianData_t2.m_deltaVelocitiesUnitImpulse[0];
+
+ btMatrix3x3 rot(normal.getX(), normal.getY(), normal.getZ(),
+ t1.getX(), t1.getY(), t1.getZ(),
+ t2.getX(), t2.getY(), t2.getZ()); // world frame to local frame
+ const int ndof = multibodyLinkCol->m_multiBody->getNumDofs() + 6;
+ btMatrix3x3 local_impulse_matrix = (Diagonal(n.m_im) + OuterProduct(J_n, J_t1, J_t2, u_n, u_t1, u_t2, ndof)).inverse();
+ c.m_c0 = rot.transpose() * local_impulse_matrix * rot;
+ c.jacobianData_normal = jacobianData_normal;
+ c.jacobianData_t1 = jacobianData_t1;
+ c.jacobianData_t2 = jacobianData_t2;
+ c.t1 = t1;
+ c.t2 = t2;
+ }
+ }
+ psb->m_nodeRigidContacts.push_back(c);
+ }
+ }
}
}
btSoftBody* psb;
@@ -905,6 +1143,112 @@ struct btSoftColliders
btScalar dynmargin;
btScalar stamargin;
};
+
+ //
+ // CollideSDF_RDF
+ //
+ struct CollideSDF_RDF : btDbvt::ICollide
+ {
+ void Process(const btDbvtNode* leaf)
+ {
+ btSoftBody::Face* face = (btSoftBody::Face*)leaf->data;
+ DoNode(*face);
+ }
+ void DoNode(btSoftBody::Face& f) const
+ {
+ btSoftBody::Node* n0 = f.m_n[0];
+ btSoftBody::Node* n1 = f.m_n[1];
+ btSoftBody::Node* n2 = f.m_n[2];
+
+ const btScalar m = (n0->m_im > 0 && n1->m_im > 0 && n2->m_im > 0 )? dynmargin : stamargin;
+ btSoftBody::DeformableFaceRigidContact c;
+ btVector3 contact_point;
+ btVector3 bary;
+ if (psb->checkDeformableFaceContact(m_colObj1Wrap, f, contact_point, bary, m, c.m_cti, true))
+ {
+ f.m_pcontact[3] = 1;
+ btScalar ima = n0->m_im + n1->m_im + n2->m_im;
+ const btScalar imb = m_rigidBody ? m_rigidBody->getInvMass() : 0.f;
+ // todo: collision between multibody and fixed deformable face will be missed.
+ const btScalar ms = ima + imb;
+ if (ms > 0)
+ {
+ // resolve contact at x_n
+ psb->checkDeformableFaceContact(m_colObj1Wrap, f, contact_point, bary, m, c.m_cti, /*predict = */ false);
+ btSoftBody::sCti& cti = c.m_cti;
+ c.m_contactPoint = contact_point;
+ c.m_bary = bary;
+ // todo xuchenhan@: this is assuming mass of all vertices are the same. Need to modify if mass are different for distinct vertices
+ c.m_weights = btScalar(2)/(btScalar(1) + bary.length2()) * bary;
+ c.m_face = &f;
+ const btScalar fc = psb->m_cfg.kDF * m_colObj1Wrap->getCollisionObject()->getFriction();
+
+ // the effective inverse mass of the face as in https://graphics.stanford.edu/papers/cloth-sig02/cloth.pdf
+ ima = bary.getX()*c.m_weights.getX() * n0->m_im + bary.getY()*c.m_weights.getY() * n1->m_im + bary.getZ()*c.m_weights.getZ() * n2->m_im;
+
+ c.m_c2 = ima;
+ c.m_c3 = fc;
+ c.m_c4 = m_colObj1Wrap->getCollisionObject()->isStaticOrKinematicObject() ? psb->m_cfg.kKHR : psb->m_cfg.kCHR;
+ if (cti.m_colObj->getInternalType() == btCollisionObject::CO_RIGID_BODY)
+ {
+ const btTransform& wtr = m_rigidBody ? m_rigidBody->getWorldTransform() : m_colObj1Wrap->getCollisionObject()->getWorldTransform();
+ static const btMatrix3x3 iwiStatic(0, 0, 0, 0, 0, 0, 0, 0, 0);
+ const btMatrix3x3& iwi = m_rigidBody ? m_rigidBody->getInvInertiaTensorWorld() : iwiStatic;
+ const btVector3 ra = contact_point - wtr.getOrigin();
+
+ // we do not scale the impulse matrix by dt
+ c.m_c0 = ImpulseMatrix(1, ima, imb, iwi, ra);
+ c.m_c1 = ra;
+ }
+ else if (cti.m_colObj->getInternalType() == btCollisionObject::CO_FEATHERSTONE_LINK)
+ {
+ btMultiBodyLinkCollider* multibodyLinkCol = (btMultiBodyLinkCollider*)btMultiBodyLinkCollider::upcast(cti.m_colObj);
+ if (multibodyLinkCol)
+ {
+ btVector3 normal = cti.m_normal;
+ btVector3 t1 = generateUnitOrthogonalVector(normal);
+ btVector3 t2 = btCross(normal, t1);
+ btMultiBodyJacobianData jacobianData_normal, jacobianData_t1, jacobianData_t2;
+ findJacobian(multibodyLinkCol, jacobianData_normal, contact_point, normal);
+ findJacobian(multibodyLinkCol, jacobianData_t1, contact_point, t1);
+ findJacobian(multibodyLinkCol, jacobianData_t2, contact_point, t2);
+
+ btScalar* J_n = &jacobianData_normal.m_jacobians[0];
+ btScalar* J_t1 = &jacobianData_t1.m_jacobians[0];
+ btScalar* J_t2 = &jacobianData_t2.m_jacobians[0];
+
+ btScalar* u_n = &jacobianData_normal.m_deltaVelocitiesUnitImpulse[0];
+ btScalar* u_t1 = &jacobianData_t1.m_deltaVelocitiesUnitImpulse[0];
+ btScalar* u_t2 = &jacobianData_t2.m_deltaVelocitiesUnitImpulse[0];
+
+ btMatrix3x3 rot(normal.getX(), normal.getY(), normal.getZ(),
+ t1.getX(), t1.getY(), t1.getZ(),
+ t2.getX(), t2.getY(), t2.getZ()); // world frame to local frame
+ const int ndof = multibodyLinkCol->m_multiBody->getNumDofs() + 6;
+ btMatrix3x3 local_impulse_matrix = (Diagonal(ima) + OuterProduct(J_n, J_t1, J_t2, u_n, u_t1, u_t2, ndof)).inverse();
+ c.m_c0 = rot.transpose() * local_impulse_matrix * rot;
+ c.jacobianData_normal = jacobianData_normal;
+ c.jacobianData_t1 = jacobianData_t1;
+ c.jacobianData_t2 = jacobianData_t2;
+ c.t1 = t1;
+ c.t2 = t2;
+ }
+ }
+ psb->m_faceRigidContacts.push_back(c);
+ }
+ }
+ else
+ {
+ f.m_pcontact[3] = 0;
+ }
+ }
+ btSoftBody* psb;
+ const btCollisionObjectWrapper* m_colObj1Wrap;
+ btRigidBody* m_rigidBody;
+ btScalar dynmargin;
+ btScalar stamargin;
+ };
+
//
// CollideVF_SS
//
@@ -915,6 +1259,12 @@ struct btSoftColliders
{
btSoftBody::Node* node = (btSoftBody::Node*)lnode->data;
btSoftBody::Face* face = (btSoftBody::Face*)lface->data;
+ for (int i = 0; i < 3; ++i)
+ {
+ if (face->m_n[i] == node)
+ continue;
+ }
+
btVector3 o = node->m_x;
btVector3 p;
btScalar d = SIMD_INFINITY;
@@ -944,7 +1294,7 @@ struct btSoftColliders
c.m_node = node;
c.m_face = face;
c.m_weights = w;
- c.m_friction = btMax(psb[0]->m_cfg.kDF, psb[1]->m_cfg.kDF);
+ c.m_friction = btMax (psb[0]->m_cfg.kDF, psb[1]->m_cfg.kDF);
c.m_cfm[0] = ma / ms * psb[0]->m_cfg.kSHR;
c.m_cfm[1] = mb / ms * psb[1]->m_cfg.kSHR;
psb[0]->m_scontacts.push_back(c);
@@ -954,6 +1304,137 @@ struct btSoftColliders
btSoftBody* psb[2];
btScalar mrg;
};
+
+
+ //
+ // CollideVF_DD
+ //
+ struct CollideVF_DD : btDbvt::ICollide
+ {
+ void Process(const btDbvtNode* lnode,
+ const btDbvtNode* lface)
+ {
+ btSoftBody::Node* node = (btSoftBody::Node*)lnode->data;
+ btSoftBody::Face* face = (btSoftBody::Face*)lface->data;
+
+ btVector3 o = node->m_x;
+ btVector3 p;
+ btScalar d = SIMD_INFINITY;
+ ProjectOrigin(face->m_n[0]->m_x - o,
+ face->m_n[1]->m_x - o,
+ face->m_n[2]->m_x - o,
+ p, d);
+ const btScalar m = mrg + (o - node->m_q).safeNorm() * 2;
+ if (d < (m * m))
+ {
+ const btSoftBody::Node* n[] = {face->m_n[0], face->m_n[1], face->m_n[2]};
+ const btVector3 w = BaryCoord(n[0]->m_x, n[1]->m_x, n[2]->m_x, p + o);
+ const btScalar ma = node->m_im;
+ btScalar mb = BaryEval(n[0]->m_im, n[1]->m_im, n[2]->m_im, w);
+ if ((n[0]->m_im <= 0) ||
+ (n[1]->m_im <= 0) ||
+ (n[2]->m_im <= 0))
+ {
+ mb = 0;
+ }
+ const btScalar ms = ma + mb;
+ if (ms > 0)
+ {
+ btSoftBody::DeformableFaceNodeContact c;
+ if (useFaceNormal)
+ c.m_normal = face->m_normal;
+ else
+ c.m_normal = p / -btSqrt(d);
+ c.m_margin = mrg;
+ c.m_node = node;
+ c.m_face = face;
+ c.m_bary = w;
+ // todo xuchenhan@: this is assuming mass of all vertices are the same. Need to modify if mass are different for distinct vertices
+ c.m_weights = btScalar(2)/(btScalar(1) + w.length2()) * w;
+ c.m_friction = psb[0]->m_cfg.kDF * psb[1]->m_cfg.kDF;
+ // the effective inverse mass of the face as in https://graphics.stanford.edu/papers/cloth-sig02/cloth.pdf
+ c.m_imf = c.m_bary[0]*c.m_weights[0] * n[0]->m_im + c.m_bary[1]*c.m_weights[1] * n[1]->m_im + c.m_bary[2]*c.m_weights[2] * n[2]->m_im;
+ c.m_c0 = btScalar(1)/(ma + c.m_imf);
+ psb[0]->m_faceNodeContacts.push_back(c);
+ }
+ }
+ }
+ btSoftBody* psb[2];
+ btScalar mrg;
+ bool useFaceNormal;
+ };
+
+ //
+ // CollideFF_DD
+ //
+ struct CollideFF_DD : btDbvt::ICollide
+ {
+ void Process(const btDbvntNode* lface1,
+ const btDbvntNode* lface2)
+ {
+ btSoftBody::Face* f = (btSoftBody::Face*)lface1->data;
+ btSoftBody::Face* face = (btSoftBody::Face*)lface2->data;
+ for (int node_id = 0; node_id < 3; ++node_id)
+ {
+ btSoftBody::Node* node = f->m_n[node_id];
+ bool skip = false;
+ for (int i = 0; i < 3; ++i)
+ {
+ if (face->m_n[i] == node)
+ {
+ skip = true;
+ break;
+ }
+ }
+ if (skip)
+ continue;
+ btVector3 o = node->m_x;
+ btVector3 p;
+ btScalar d = SIMD_INFINITY;
+ ProjectOrigin(face->m_n[0]->m_x - o,
+ face->m_n[1]->m_x - o,
+ face->m_n[2]->m_x - o,
+ p, d);
+ const btScalar m = mrg + (o - node->m_q).safeNorm() * 2;
+ if (d < (m * m))
+ {
+ const btSoftBody::Node* n[] = {face->m_n[0], face->m_n[1], face->m_n[2]};
+ const btVector3 w = BaryCoord(n[0]->m_x, n[1]->m_x, n[2]->m_x, p + o);
+ const btScalar ma = node->m_im;
+ btScalar mb = BaryEval(n[0]->m_im, n[1]->m_im, n[2]->m_im, w);
+ if ((n[0]->m_im <= 0) ||
+ (n[1]->m_im <= 0) ||
+ (n[2]->m_im <= 0))
+ {
+ mb = 0;
+ }
+ const btScalar ms = ma + mb;
+ if (ms > 0)
+ {
+ btSoftBody::DeformableFaceNodeContact c;
+ if (useFaceNormal)
+ c.m_normal = face->m_normal;
+ else
+ c.m_normal = p / -btSqrt(d);
+ c.m_margin = mrg;
+ c.m_node = node;
+ c.m_face = face;
+ c.m_bary = w;
+ // todo xuchenhan@: this is assuming mass of all vertices are the same. Need to modify if mass are different for distinct vertices
+ c.m_weights = btScalar(2)/(btScalar(1) + w.length2()) * w;
+ c.m_friction = psb[0]->m_cfg.kDF * psb[1]->m_cfg.kDF;
+ // the effective inverse mass of the face as in https://graphics.stanford.edu/papers/cloth-sig02/cloth.pdf
+ c.m_imf = c.m_bary[0]*c.m_weights[0] * n[0]->m_im + c.m_bary[1]*c.m_weights[1] * n[1]->m_im + c.m_bary[2]*c.m_weights[2] * n[2]->m_im;
+ c.m_c0 = btScalar(1)/(ma + c.m_imf);
+ psb[0]->m_faceNodeContacts.push_back(c);
+ }
+ }
+ }
+ }
+ btSoftBody* psb[2];
+ btScalar mrg;
+ bool useFaceNormal;
+ };
};
#endif //_BT_SOFT_BODY_INTERNALS_H
diff --git a/thirdparty/bullet/BulletSoftBody/btSoftBodySolvers.h b/thirdparty/bullet/BulletSoftBody/btSoftBodySolvers.h
index dcf5082650..c4ac4141aa 100644
--- a/thirdparty/bullet/BulletSoftBody/btSoftBodySolvers.h
+++ b/thirdparty/bullet/BulletSoftBody/btSoftBodySolvers.h
@@ -35,7 +35,8 @@ public:
CL_SOLVER,
CL_SIMD_SOLVER,
DX_SOLVER,
- DX_SIMD_SOLVER
+ DX_SIMD_SOLVER,
+ DEFORMABLE_SOLVER
};
protected:
@@ -71,10 +72,10 @@ public:
virtual void copyBackToSoftBodies(bool bMove = true) = 0;
/** Predict motion of soft bodies into next timestep */
- virtual void predictMotion(float solverdt) = 0;
+ virtual void predictMotion(btScalar solverdt) = 0;
/** Solve constraints for a set of soft bodies */
- virtual void solveConstraints(float solverdt) = 0;
+ virtual void solveConstraints(btScalar solverdt) = 0;
/** Perform necessary per-step updates of soft bodies such as recomputing normals and bounding boxes */
virtual void updateSoftBodies() = 0;
diff --git a/thirdparty/bullet/BulletSoftBody/btSparseSDF.h b/thirdparty/bullet/BulletSoftBody/btSparseSDF.h
index a52b2cb1cc..eb290a1dbd 100644
--- a/thirdparty/bullet/BulletSoftBody/btSparseSDF.h
+++ b/thirdparty/bullet/BulletSoftBody/btSparseSDF.h
@@ -20,27 +20,38 @@ subject to the following restrictions:
#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
#include "BulletCollision/NarrowPhaseCollision/btGjkEpa2.h"
-// Modified Paul Hsieh hash
-template <const int DWORDLEN>
-unsigned int HsiehHash(const void* pdata)
-{
- const unsigned short* data = (const unsigned short*)pdata;
- unsigned hash = DWORDLEN << 2, tmp;
- for (int i = 0; i < DWORDLEN; ++i)
- {
- hash += data[0];
- tmp = (data[1] << 11) ^ hash;
- hash = (hash << 16) ^ tmp;
- data += 2;
- hash += hash >> 11;
- }
- hash ^= hash << 3;
- hash += hash >> 5;
- hash ^= hash << 4;
- hash += hash >> 17;
- hash ^= hash << 25;
- hash += hash >> 6;
- return (hash);
+// Fast Hash
+
+#if !defined (get16bits)
+#define get16bits(d) ((((unsigned int)(((const unsigned char *)(d))[1])) << 8)\
++(unsigned int)(((const unsigned char *)(d))[0]) )
+#endif
+//
+// super hash function by Paul Hsieh
+//
+inline unsigned int HsiehHash (const char * data, int len) {
+ unsigned int hash = len, tmp;
+ len>>=2;
+
+ /* Main loop */
+ for (;len > 0; len--) {
+ hash += get16bits (data);
+ tmp = (get16bits (data+2) << 11) ^ hash;
+ hash = (hash << 16) ^ tmp;
+ data += 2*sizeof (unsigned short);
+ hash += hash >> 11;
+ }
+
+
+ /* Force "avalanching" of final 127 bits */
+ hash ^= hash << 3;
+ hash += hash >> 5;
+ hash ^= hash << 4;
+ hash += hash >> 17;
+ hash ^= hash << 25;
+ hash += hash >> 6;
+
+ return hash;
}
template <const int CELLSIZE>
@@ -70,12 +81,17 @@ struct btSparseSdf
btAlignedObjectArray<Cell*> cells;
btScalar voxelsz;
+ btScalar m_defaultVoxelsz;
int puid;
int ncells;
int m_clampCells;
int nprobes;
int nqueries;
+ ~btSparseSdf()
+ {
+ Reset();
+ }
//
// Methods
//
@@ -87,9 +103,16 @@ struct btSparseSdf
//if this limit is reached, the SDF is reset (at the cost of some performance during the reset)
m_clampCells = clampCells;
cells.resize(hashsize, 0);
+ m_defaultVoxelsz = 0.25;
Reset();
}
//
+
+ void setDefaultVoxelsz(btScalar sz)
+ {
+ m_defaultVoxelsz = sz;
+ }
+
void Reset()
{
for (int i = 0, ni = cells.size(); i < ni; ++i)
@@ -103,7 +126,7 @@ struct btSparseSdf
pc = pn;
}
}
- voxelsz = 0.25;
+ voxelsz = m_defaultVoxelsz;
puid = 0;
ncells = 0;
nprobes = 1;
@@ -197,6 +220,9 @@ struct btSparseSdf
}
else
{
+ // printf("c->hash/c[0][1][2]=%d,%d,%d,%d\n", c->hash, c->c[0], c->c[1],c->c[2]);
+ //printf("h,ixb,iyb,izb=%d,%d,%d,%d\n", h,ix.b, iy.b, iz.b);
+
c = c->next;
}
}
@@ -248,7 +274,7 @@ struct btSparseSdf
Lerp(gy[2], gy[3], ix.f), iz.f));
normal.setZ(Lerp(Lerp(gz[0], gz[1], ix.f),
Lerp(gz[2], gz[3], ix.f), iy.f));
- normal = normal.normalized();
+ normal.safeNormalize();
#else
normal = btVector3(d[1] - d[0], d[3] - d[0], d[4] - d[0]).normalized();
#endif
@@ -322,19 +348,22 @@ struct btSparseSdf
{
struct btS
{
- int x, y, z;
+ int x, y, z, w;
void* p;
};
btS myset;
+ //memset may be needed in case of additional (uninitialized) padding!
+ //memset(&myset, 0, sizeof(btS));
myset.x = x;
myset.y = y;
myset.z = z;
+ myset.w = 0;
myset.p = (void*)shape;
- const void* ptr = &myset;
+ const char* ptr = (const char*)&myset;
- unsigned int result = HsiehHash<sizeof(btS) / 4>(ptr);
+ unsigned int result = HsiehHash(ptr, sizeof(btS) );
return result;
}
diff --git a/thirdparty/bullet/LinearMath/btImplicitQRSVD.h b/thirdparty/bullet/LinearMath/btImplicitQRSVD.h
new file mode 100644
index 0000000000..7b4cfaf21e
--- /dev/null
+++ b/thirdparty/bullet/LinearMath/btImplicitQRSVD.h
@@ -0,0 +1,916 @@
+/**
+ Bullet Continuous Collision Detection and Physics Library
+ Copyright (c) 2019 Google Inc. http://bulletphysics.org
+ 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.
+
+ Copyright (c) 2016 Theodore Gast, Chuyuan Fu, Chenfanfu Jiang, Joseph Teran
+
+ 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.
+
+ If the code is used in an article, the following paper shall be cited:
+ @techreport{qrsvd:2016,
+ title={Implicit-shifted Symmetric QR Singular Value Decomposition of 3x3 Matrices},
+ author={Gast, Theodore and Fu, Chuyuan and Jiang, Chenfanfu and Teran, Joseph},
+ year={2016},
+ institution={University of California Los Angeles}
+ }
+
+ 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 btImplicitQRSVD_h
+#define btImplicitQRSVD_h
+
+#include "btMatrix3x3.h"
+class btMatrix2x2
+{
+public:
+ btScalar m_00, m_01, m_10, m_11;
+ btMatrix2x2(): m_00(0), m_10(0), m_01(0), m_11(0)
+ {
+ }
+ btMatrix2x2(const btMatrix2x2& other): m_00(other.m_00),m_01(other.m_01),m_10(other.m_10),m_11(other.m_11)
+ {}
+ btScalar& operator()(int i, int j)
+ {
+ if (i == 0 && j == 0)
+ return m_00;
+ if (i == 1 && j == 0)
+ return m_10;
+ if (i == 0 && j == 1)
+ return m_01;
+ if (i == 1 && j == 1)
+ return m_11;
+ btAssert(false);
+ return m_00;
+ }
+ const btScalar& operator()(int i, int j) const
+ {
+ if (i == 0 && j == 0)
+ return m_00;
+ if (i == 1 && j == 0)
+ return m_10;
+ if (i == 0 && j == 1)
+ return m_01;
+ if (i == 1 && j == 1)
+ return m_11;
+ btAssert(false);
+ return m_00;
+ }
+ void setIdentity()
+ {
+ m_00 = 1;
+ m_11 = 1;
+ m_01 = 0;
+ m_10 = 0;
+ }
+};
+
+static inline btScalar copySign(btScalar x, btScalar y) {
+ if ((x < 0 && y > 0) || (x > 0 && y < 0))
+ return -x;
+ return x;
+}
+
+/**
+ Class for givens rotation.
+ Row rotation G*A corresponds to something like
+ c -s 0
+ ( s c 0 ) A
+ 0 0 1
+ Column rotation A G' corresponds to something like
+ c -s 0
+ A ( s c 0 )
+ 0 0 1
+
+ c and s are always computed so that
+ ( c -s ) ( a ) = ( * )
+ s c b ( 0 )
+
+ Assume rowi<rowk.
+ */
+
+class GivensRotation {
+public:
+ int rowi;
+ int rowk;
+ btScalar c;
+ btScalar s;
+
+ inline GivensRotation(int rowi_in, int rowk_in)
+ : rowi(rowi_in)
+ , rowk(rowk_in)
+ , c(1)
+ , s(0)
+ {
+ }
+
+ inline GivensRotation(btScalar a, btScalar b, int rowi_in, int rowk_in)
+ : rowi(rowi_in)
+ , rowk(rowk_in)
+ {
+ compute(a, b);
+ }
+
+ ~GivensRotation() {}
+
+ inline void transposeInPlace()
+ {
+ s = -s;
+ }
+
+ /**
+ Compute c and s from a and b so that
+ ( c -s ) ( a ) = ( * )
+ s c b ( 0 )
+ */
+ inline void compute(const btScalar a, const btScalar b)
+ {
+ btScalar d = a * a + b * b;
+ c = 1;
+ s = 0;
+ if (d > SIMD_EPSILON) {
+ btScalar sqrtd = btSqrt(d);
+ if (sqrtd>SIMD_EPSILON)
+ {
+ btScalar t = btScalar(1.0)/sqrtd;
+ c = a * t;
+ s = -b * t;
+ }
+ }
+ }
+
+ /**
+ This function computes c and s so that
+ ( c -s ) ( a ) = ( 0 )
+ s c b ( * )
+ */
+ inline void computeUnconventional(const btScalar a, const btScalar b)
+ {
+ btScalar d = a * a + b * b;
+ c = 0;
+ s = 1;
+ if (d > SIMD_EPSILON) {
+ btScalar t = btScalar(1.0)/btSqrt(d);
+ s = a * t;
+ c = b * t;
+ }
+ }
+ /**
+ Fill the R with the entries of this rotation
+ */
+ inline void fill(const btMatrix3x3& R) const
+ {
+ btMatrix3x3& A = const_cast<btMatrix3x3&>(R);
+ A.setIdentity();
+ A[rowi][rowi] = c;
+ A[rowk][rowi] = -s;
+ A[rowi][rowk] = s;
+ A[rowk][rowk] = c;
+ }
+
+ inline void fill(const btMatrix2x2& R) const
+ {
+ btMatrix2x2& A = const_cast<btMatrix2x2&>(R);
+ A(rowi,rowi) = c;
+ A(rowk,rowi) = -s;
+ A(rowi,rowk) = s;
+ A(rowk,rowk) = c;
+ }
+
+ /**
+ This function does something like
+ c -s 0
+ ( s c 0 ) A -> A
+ 0 0 1
+ It only affects row i and row k of A.
+ */
+ inline void rowRotation(btMatrix3x3& A) const
+ {
+ for (int j = 0; j < 3; j++) {
+ btScalar tau1 = A[rowi][j];
+ btScalar tau2 = A[rowk][j];
+ A[rowi][j] = c * tau1 - s * tau2;
+ A[rowk][j] = s * tau1 + c * tau2;
+ }
+ }
+ inline void rowRotation(btMatrix2x2& A) const
+ {
+ for (int j = 0; j < 2; j++) {
+ btScalar tau1 = A(rowi,j);
+ btScalar tau2 = A(rowk,j);
+ A(rowi,j) = c * tau1 - s * tau2;
+ A(rowk,j) = s * tau1 + c * tau2;
+ }
+ }
+
+ /**
+ This function does something like
+ c s 0
+ A ( -s c 0 ) -> A
+ 0 0 1
+ It only affects column i and column k of A.
+ */
+ inline void columnRotation(btMatrix3x3& A) const
+ {
+ for (int j = 0; j < 3; j++) {
+ btScalar tau1 = A[j][rowi];
+ btScalar tau2 = A[j][rowk];
+ A[j][rowi] = c * tau1 - s * tau2;
+ A[j][rowk] = s * tau1 + c * tau2;
+ }
+ }
+ inline void columnRotation(btMatrix2x2& A) const
+ {
+ for (int j = 0; j < 2; j++) {
+ btScalar tau1 = A(j,rowi);
+ btScalar tau2 = A(j,rowk);
+ A(j,rowi) = c * tau1 - s * tau2;
+ A(j,rowk) = s * tau1 + c * tau2;
+ }
+ }
+
+ /**
+ Multiply givens must be for same row and column
+ **/
+ inline void operator*=(const GivensRotation& A)
+ {
+ btScalar new_c = c * A.c - s * A.s;
+ btScalar new_s = s * A.c + c * A.s;
+ c = new_c;
+ s = new_s;
+ }
+
+ /**
+ Multiply givens must be for same row and column
+ **/
+ inline GivensRotation operator*(const GivensRotation& A) const
+ {
+ GivensRotation r(*this);
+ r *= A;
+ return r;
+ }
+};
+
+/**
+ \brief zero chasing the 3X3 matrix to bidiagonal form
+ original form of H: x x 0
+ x x x
+ 0 0 x
+ after zero chase:
+ x x 0
+ 0 x x
+ 0 0 x
+ */
+inline void zeroChase(btMatrix3x3& H, btMatrix3x3& U, btMatrix3x3& V)
+{
+
+ /**
+ Reduce H to of form
+ x x +
+ 0 x x
+ 0 0 x
+ */
+ GivensRotation r1(H[0][0], H[1][0], 0, 1);
+ /**
+ Reduce H to of form
+ x x 0
+ 0 x x
+ 0 + x
+ Can calculate r2 without multiplying by r1 since both entries are in first two
+ rows thus no need to divide by sqrt(a^2+b^2)
+ */
+ GivensRotation r2(1, 2);
+ if (H[1][0] != 0)
+ r2.compute(H[0][0] * H[0][1] + H[1][0] * H[1][1], H[0][0] * H[0][2] + H[1][0] * H[1][2]);
+ else
+ r2.compute(H[0][1], H[0][2]);
+
+ r1.rowRotation(H);
+
+ /* GivensRotation<T> r2(H(0, 1), H(0, 2), 1, 2); */
+ r2.columnRotation(H);
+ r2.columnRotation(V);
+
+ /**
+ Reduce H to of form
+ x x 0
+ 0 x x
+ 0 0 x
+ */
+ GivensRotation r3(H[1][1], H[2][1], 1, 2);
+ r3.rowRotation(H);
+
+ // Save this till end for better cache coherency
+ // r1.rowRotation(u_transpose);
+ // r3.rowRotation(u_transpose);
+ r1.columnRotation(U);
+ r3.columnRotation(U);
+}
+
+/**
+ \brief make a 3X3 matrix to upper bidiagonal form
+ original form of H: x x x
+ x x x
+ x x x
+ after zero chase:
+ x x 0
+ 0 x x
+ 0 0 x
+ */
+inline void makeUpperBidiag(btMatrix3x3& H, btMatrix3x3& U, btMatrix3x3& V)
+{
+ U.setIdentity();
+ V.setIdentity();
+
+ /**
+ Reduce H to of form
+ x x x
+ x x x
+ 0 x x
+ */
+
+ GivensRotation r(H[1][0], H[2][0], 1, 2);
+ r.rowRotation(H);
+ // r.rowRotation(u_transpose);
+ r.columnRotation(U);
+ // zeroChase(H, u_transpose, V);
+ zeroChase(H, U, V);
+}
+
+/**
+ \brief make a 3X3 matrix to lambda shape
+ original form of H: x x x
+ * x x x
+ * x x x
+ after :
+ * x 0 0
+ * x x 0
+ * x 0 x
+ */
+inline void makeLambdaShape(btMatrix3x3& H, btMatrix3x3& U, btMatrix3x3& V)
+{
+ U.setIdentity();
+ V.setIdentity();
+
+ /**
+ Reduce H to of form
+ * x x 0
+ * x x x
+ * x x x
+ */
+
+ GivensRotation r1(H[0][1], H[0][2], 1, 2);
+ r1.columnRotation(H);
+ r1.columnRotation(V);
+
+ /**
+ Reduce H to of form
+ * x x 0
+ * x x 0
+ * x x x
+ */
+
+ r1.computeUnconventional(H[1][2], H[2][2]);
+ r1.rowRotation(H);
+ r1.columnRotation(U);
+
+ /**
+ Reduce H to of form
+ * x x 0
+ * x x 0
+ * x 0 x
+ */
+
+ GivensRotation r2(H[2][0], H[2][1], 0, 1);
+ r2.columnRotation(H);
+ r2.columnRotation(V);
+
+ /**
+ Reduce H to of form
+ * x 0 0
+ * x x 0
+ * x 0 x
+ */
+ r2.computeUnconventional(H[0][1], H[1][1]);
+ r2.rowRotation(H);
+ r2.columnRotation(U);
+}
+
+/**
+ \brief 2x2 polar decomposition.
+ \param[in] A matrix.
+ \param[out] R Robustly a rotation matrix.
+ \param[out] S_Sym Symmetric. Whole matrix is stored
+
+ Polar guarantees negative sign is on the small magnitude singular value.
+ S is guaranteed to be the closest one to identity.
+ R is guaranteed to be the closest rotation to A.
+ */
+inline void polarDecomposition(const btMatrix2x2& A,
+ GivensRotation& R,
+ const btMatrix2x2& S_Sym)
+{
+ btScalar a = (A(0, 0) + A(1, 1)), b = (A(1, 0) - A(0, 1));
+ btScalar denominator = btSqrt(a*a+b*b);
+ R.c = (btScalar)1;
+ R.s = (btScalar)0;
+ if (denominator > SIMD_EPSILON) {
+ /*
+ No need to use a tolerance here because x(0) and x(1) always have
+ smaller magnitude then denominator, therefore overflow never happens.
+ In Bullet, we use a tolerance anyway.
+ */
+ R.c = a / denominator;
+ R.s = -b / denominator;
+ }
+ btMatrix2x2& S = const_cast<btMatrix2x2&>(S_Sym);
+ S = A;
+ R.rowRotation(S);
+}
+
+inline void polarDecomposition(const btMatrix2x2& A,
+ const btMatrix2x2& R,
+ const btMatrix2x2& S_Sym)
+{
+ GivensRotation r(0, 1);
+ polarDecomposition(A, r, S_Sym);
+ r.fill(R);
+}
+
+/**
+ \brief 2x2 SVD (singular value decomposition) A=USV'
+ \param[in] A Input matrix.
+ \param[out] U Robustly a rotation matrix in Givens form
+ \param[out] Sigma matrix of singular values sorted with decreasing magnitude. The second one can be negative.
+ \param[out] V Robustly a rotation matrix in Givens form
+ */
+inline void singularValueDecomposition(
+ const btMatrix2x2& A,
+ GivensRotation& U,
+ const btMatrix2x2& Sigma,
+ GivensRotation& V,
+ const btScalar tol = 64 * std::numeric_limits<btScalar>::epsilon())
+{
+ btMatrix2x2& sigma = const_cast<btMatrix2x2&>(Sigma);
+ sigma.setIdentity();
+ btMatrix2x2 S_Sym;
+ polarDecomposition(A, U, S_Sym);
+ btScalar cosine, sine;
+ btScalar x = S_Sym(0, 0);
+ btScalar y = S_Sym(0, 1);
+ btScalar z = S_Sym(1, 1);
+ if (y == 0) {
+ // S is already diagonal
+ cosine = 1;
+ sine = 0;
+ sigma(0,0) = x;
+ sigma(1,1) = z;
+ }
+ else {
+ btScalar tau = 0.5 * (x - z);
+ btScalar val = tau * tau + y * y;
+ if (val > SIMD_EPSILON)
+ {
+ btScalar w = btSqrt(val);
+ // w > y > 0
+ btScalar t;
+ if (tau > 0) {
+ // tau + w > w > y > 0 ==> division is safe
+ t = y / (tau + w);
+ }
+ else {
+ // tau - w < -w < -y < 0 ==> division is safe
+ t = y / (tau - w);
+ }
+ cosine = btScalar(1) / btSqrt(t * t + btScalar(1));
+ sine = -t * cosine;
+ /*
+ V = [cosine -sine; sine cosine]
+ Sigma = V'SV. Only compute the diagonals for efficiency.
+ Also utilize symmetry of S and don't form V yet.
+ */
+ btScalar c2 = cosine * cosine;
+ btScalar csy = 2 * cosine * sine * y;
+ btScalar s2 = sine * sine;
+ sigma(0,0) = c2 * x - csy + s2 * z;
+ sigma(1,1) = s2 * x + csy + c2 * z;
+ } else
+ {
+ cosine = 1;
+ sine = 0;
+ sigma(0,0) = x;
+ sigma(1,1) = z;
+ }
+ }
+
+ // Sorting
+ // Polar already guarantees negative sign is on the small magnitude singular value.
+ if (sigma(0,0) < sigma(1,1)) {
+ std::swap(sigma(0,0), sigma(1,1));
+ V.c = -sine;
+ V.s = cosine;
+ }
+ else {
+ V.c = cosine;
+ V.s = sine;
+ }
+ U *= V;
+}
+
+/**
+ \brief 2x2 SVD (singular value decomposition) A=USV'
+ \param[in] A Input matrix.
+ \param[out] U Robustly a rotation matrix.
+ \param[out] Sigma Vector of singular values sorted with decreasing magnitude. The second one can be negative.
+ \param[out] V Robustly a rotation matrix.
+ */
+inline void singularValueDecomposition(
+ const btMatrix2x2& A,
+ const btMatrix2x2& U,
+ const btMatrix2x2& Sigma,
+ const btMatrix2x2& V,
+ const btScalar tol = 64 * std::numeric_limits<btScalar>::epsilon())
+{
+ GivensRotation gv(0, 1);
+ GivensRotation gu(0, 1);
+ singularValueDecomposition(A, gu, Sigma, gv);
+
+ gu.fill(U);
+ gv.fill(V);
+}
+
+/**
+ \brief compute wilkinsonShift of the block
+ a1 b1
+ b1 a2
+ based on the wilkinsonShift formula
+ mu = c + d - sign (d) \ sqrt (d*d + b*b), where d = (a-c)/2
+
+ */
+inline btScalar wilkinsonShift(const btScalar a1, const btScalar b1, const btScalar a2)
+{
+ btScalar d = (btScalar)0.5 * (a1 - a2);
+ btScalar bs = b1 * b1;
+ btScalar val = d * d + bs;
+ if (val>SIMD_EPSILON)
+ {
+ btScalar denom = btFabs(d) + btSqrt(val);
+
+ btScalar mu = a2 - copySign(bs / (denom), d);
+ // T mu = a2 - bs / ( d + sign_d*sqrt (d*d + bs));
+ return mu;
+ }
+ return a2;
+}
+
+/**
+ \brief Helper function of 3X3 SVD for processing 2X2 SVD
+ */
+template <int t>
+inline void process(btMatrix3x3& B, btMatrix3x3& U, btVector3& sigma, btMatrix3x3& V)
+{
+ int other = (t == 1) ? 0 : 2;
+ GivensRotation u(0, 1);
+ GivensRotation v(0, 1);
+ sigma[other] = B[other][other];
+
+ btMatrix2x2 B_sub, sigma_sub;
+ if (t == 0)
+ {
+ B_sub.m_00 = B[0][0];
+ B_sub.m_10 = B[1][0];
+ B_sub.m_01 = B[0][1];
+ B_sub.m_11 = B[1][1];
+ sigma_sub.m_00 = sigma[0];
+ sigma_sub.m_11 = sigma[1];
+// singularValueDecomposition(B.template block<2, 2>(t, t), u, sigma.template block<2, 1>(t, 0), v);
+ singularValueDecomposition(B_sub, u, sigma_sub, v);
+ B[0][0] = B_sub.m_00;
+ B[1][0] = B_sub.m_10;
+ B[0][1] = B_sub.m_01;
+ B[1][1] = B_sub.m_11;
+ sigma[0] = sigma_sub.m_00;
+ sigma[1] = sigma_sub.m_11;
+ }
+ else
+ {
+ B_sub.m_00 = B[1][1];
+ B_sub.m_10 = B[2][1];
+ B_sub.m_01 = B[1][2];
+ B_sub.m_11 = B[2][2];
+ sigma_sub.m_00 = sigma[1];
+ sigma_sub.m_11 = sigma[2];
+ // singularValueDecomposition(B.template block<2, 2>(t, t), u, sigma.template block<2, 1>(t, 0), v);
+ singularValueDecomposition(B_sub, u, sigma_sub, v);
+ B[1][1] = B_sub.m_00;
+ B[2][1] = B_sub.m_10;
+ B[1][2] = B_sub.m_01;
+ B[2][2] = B_sub.m_11;
+ sigma[1] = sigma_sub.m_00;
+ sigma[2] = sigma_sub.m_11;
+ }
+ u.rowi += t;
+ u.rowk += t;
+ v.rowi += t;
+ v.rowk += t;
+ u.columnRotation(U);
+ v.columnRotation(V);
+}
+
+/**
+ \brief Helper function of 3X3 SVD for flipping signs due to flipping signs of sigma
+ */
+inline void flipSign(int i, btMatrix3x3& U, btVector3& sigma)
+{
+ sigma[i] = -sigma[i];
+ U[0][i] = -U[0][i];
+ U[1][i] = -U[1][i];
+ U[2][i] = -U[2][i];
+}
+
+inline void flipSign(int i, btMatrix3x3& U)
+{
+ U[0][i] = -U[0][i];
+ U[1][i] = -U[1][i];
+ U[2][i] = -U[2][i];
+}
+
+inline void swapCol(btMatrix3x3& A, int i, int j)
+{
+ for (int d = 0; d < 3; ++d)
+ std::swap(A[d][i], A[d][j]);
+}
+/**
+ \brief Helper function of 3X3 SVD for sorting singular values
+ */
+inline void sort(btMatrix3x3& U, btVector3& sigma, btMatrix3x3& V, int t)
+{
+ if (t == 0)
+ {
+ // Case: sigma(0) > |sigma(1)| >= |sigma(2)|
+ if (btFabs(sigma[1]) >= btFabs(sigma[2])) {
+ if (sigma[1] < 0) {
+ flipSign(1, U, sigma);
+ flipSign(2, U, sigma);
+ }
+ return;
+ }
+
+ //fix sign of sigma for both cases
+ if (sigma[2] < 0) {
+ flipSign(1, U, sigma);
+ flipSign(2, U, sigma);
+ }
+
+ //swap sigma(1) and sigma(2) for both cases
+ std::swap(sigma[1], sigma[2]);
+ // swap the col 1 and col 2 for U,V
+ swapCol(U,1,2);
+ swapCol(V,1,2);
+
+ // Case: |sigma(2)| >= sigma(0) > |simga(1)|
+ if (sigma[1] > sigma[0]) {
+ std::swap(sigma[0], sigma[1]);
+ swapCol(U,0,1);
+ swapCol(V,0,1);
+ }
+
+ // Case: sigma(0) >= |sigma(2)| > |simga(1)|
+ else {
+ flipSign(2, U);
+ flipSign(2, V);
+ }
+ }
+ else if (t == 1)
+ {
+ // Case: |sigma(0)| >= sigma(1) > |sigma(2)|
+ if (btFabs(sigma[0]) >= sigma[1]) {
+ if (sigma[0] < 0) {
+ flipSign(0, U, sigma);
+ flipSign(2, U, sigma);
+ }
+ return;
+ }
+
+ //swap sigma(0) and sigma(1) for both cases
+ std::swap(sigma[0], sigma[1]);
+ swapCol(U, 0, 1);
+ swapCol(V, 0, 1);
+
+ // Case: sigma(1) > |sigma(2)| >= |sigma(0)|
+ if (btFabs(sigma[1]) < btFabs(sigma[2])) {
+ std::swap(sigma[1], sigma[2]);
+ swapCol(U, 1, 2);
+ swapCol(V, 1, 2);
+ }
+
+ // Case: sigma(1) >= |sigma(0)| > |sigma(2)|
+ else {
+ flipSign(1, U);
+ flipSign(1, V);
+ }
+
+ // fix sign for both cases
+ if (sigma[1] < 0) {
+ flipSign(1, U, sigma);
+ flipSign(2, U, sigma);
+ }
+ }
+}
+
+/**
+ \brief 3X3 SVD (singular value decomposition) A=USV'
+ \param[in] A Input matrix.
+ \param[out] U is a rotation matrix.
+ \param[out] sigma Diagonal matrix, sorted with decreasing magnitude. The third one can be negative.
+ \param[out] V is a rotation matrix.
+ */
+inline int singularValueDecomposition(const btMatrix3x3& A,
+ btMatrix3x3& U,
+ btVector3& sigma,
+ btMatrix3x3& V,
+ btScalar tol = 128*std::numeric_limits<btScalar>::epsilon())
+{
+ using std::fabs;
+ btMatrix3x3 B = A;
+ U.setIdentity();
+ V.setIdentity();
+
+ makeUpperBidiag(B, U, V);
+
+ int count = 0;
+ btScalar mu = (btScalar)0;
+ GivensRotation r(0, 1);
+
+ btScalar alpha_1 = B[0][0];
+ btScalar beta_1 = B[0][1];
+ btScalar alpha_2 = B[1][1];
+ btScalar alpha_3 = B[2][2];
+ btScalar beta_2 = B[1][2];
+ btScalar gamma_1 = alpha_1 * beta_1;
+ btScalar gamma_2 = alpha_2 * beta_2;
+ btScalar val = alpha_1 * alpha_1 + alpha_2 * alpha_2 + alpha_3 * alpha_3 + beta_1 * beta_1 + beta_2 * beta_2;
+ if (val > SIMD_EPSILON)
+ {
+ tol *= btMax((btScalar)0.5 * btSqrt(val), (btScalar)1);
+ }
+ /**
+ Do implicit shift QR until A^T A is block diagonal
+ */
+ int max_count = 100;
+
+ while (btFabs(beta_2) > tol && btFabs(beta_1) > tol
+ && btFabs(alpha_1) > tol && btFabs(alpha_2) > tol
+ && btFabs(alpha_3) > tol
+ && count < max_count) {
+ mu = wilkinsonShift(alpha_2 * alpha_2 + beta_1 * beta_1, gamma_2, alpha_3 * alpha_3 + beta_2 * beta_2);
+
+ r.compute(alpha_1 * alpha_1 - mu, gamma_1);
+ r.columnRotation(B);
+
+ r.columnRotation(V);
+ zeroChase(B, U, V);
+
+ alpha_1 = B[0][0];
+ beta_1 = B[0][1];
+ alpha_2 = B[1][1];
+ alpha_3 = B[2][2];
+ beta_2 = B[1][2];
+ gamma_1 = alpha_1 * beta_1;
+ gamma_2 = alpha_2 * beta_2;
+ count++;
+ }
+ /**
+ Handle the cases of one of the alphas and betas being 0
+ Sorted by ease of handling and then frequency
+ of occurrence
+
+ If B is of form
+ x x 0
+ 0 x 0
+ 0 0 x
+ */
+ if (btFabs(beta_2) <= tol) {
+ process<0>(B, U, sigma, V);
+ sort(U, sigma, V,0);
+ }
+ /**
+ If B is of form
+ x 0 0
+ 0 x x
+ 0 0 x
+ */
+ else if (btFabs(beta_1) <= tol) {
+ process<1>(B, U, sigma, V);
+ sort(U, sigma, V,1);
+ }
+ /**
+ If B is of form
+ x x 0
+ 0 0 x
+ 0 0 x
+ */
+ else if (btFabs(alpha_2) <= tol) {
+ /**
+ Reduce B to
+ x x 0
+ 0 0 0
+ 0 0 x
+ */
+ GivensRotation r1(1, 2);
+ r1.computeUnconventional(B[1][2], B[2][2]);
+ r1.rowRotation(B);
+ r1.columnRotation(U);
+
+ process<0>(B, U, sigma, V);
+ sort(U, sigma, V, 0);
+ }
+ /**
+ If B is of form
+ x x 0
+ 0 x x
+ 0 0 0
+ */
+ else if (btFabs(alpha_3) <= tol) {
+ /**
+ Reduce B to
+ x x +
+ 0 x 0
+ 0 0 0
+ */
+ GivensRotation r1(1, 2);
+ r1.compute(B[1][1], B[1][2]);
+ r1.columnRotation(B);
+ r1.columnRotation(V);
+ /**
+ Reduce B to
+ x x 0
+ + x 0
+ 0 0 0
+ */
+ GivensRotation r2(0, 2);
+ r2.compute(B[0][0], B[0][2]);
+ r2.columnRotation(B);
+ r2.columnRotation(V);
+
+ process<0>(B, U, sigma, V);
+ sort(U, sigma, V, 0);
+ }
+ /**
+ If B is of form
+ 0 x 0
+ 0 x x
+ 0 0 x
+ */
+ else if (btFabs(alpha_1) <= tol) {
+ /**
+ Reduce B to
+ 0 0 +
+ 0 x x
+ 0 0 x
+ */
+ GivensRotation r1(0, 1);
+ r1.computeUnconventional(B[0][1], B[1][1]);
+ r1.rowRotation(B);
+ r1.columnRotation(U);
+
+ /**
+ Reduce B to
+ 0 0 0
+ 0 x x
+ 0 + x
+ */
+ GivensRotation r2(0, 2);
+ r2.computeUnconventional(B[0][2], B[2][2]);
+ r2.rowRotation(B);
+ r2.columnRotation(U);
+
+ process<1>(B, U, sigma, V);
+ sort(U, sigma, V, 1);
+ }
+
+ return count;
+}
+#endif /* btImplicitQRSVD_h */
diff --git a/thirdparty/bullet/LinearMath/btMatrix3x3.h b/thirdparty/bullet/LinearMath/btMatrix3x3.h
index 0a08ae409a..cc33a68664 100644
--- a/thirdparty/bullet/LinearMath/btMatrix3x3.h
+++ b/thirdparty/bullet/LinearMath/btMatrix3x3.h
@@ -125,6 +125,13 @@ public:
m_el[2] = other.m_el[2];
return *this;
}
+
+ SIMD_FORCE_INLINE btMatrix3x3(const btVector3& v0, const btVector3& v1, const btVector3& v2)
+ {
+ m_el[0] = v0;
+ m_el[1] = v1;
+ m_el[2] = v2;
+ }
#endif
diff --git a/thirdparty/bullet/LinearMath/btMatrixX.h b/thirdparty/bullet/LinearMath/btMatrixX.h
index 388c57c2d7..961c94dc63 100644
--- a/thirdparty/bullet/LinearMath/btMatrixX.h
+++ b/thirdparty/bullet/LinearMath/btMatrixX.h
@@ -338,24 +338,23 @@ struct btMatrixX
btMatrixX res(rows(), other.cols());
res.setZero();
// BT_PROFILE("btMatrixX mul");
- for (int j = 0; j < res.cols(); ++j)
+ for (int i = 0; i < rows(); ++i)
{
{
- for (int i = 0; i < res.rows(); ++i)
+ for (int j = 0; j < other.cols(); ++j)
{
T dotProd = 0;
- // T dotProd2=0;
- //int waste=0,waste2=0;
-
{
- // bool useOtherCol = true;
{
- for (int v = 0; v < rows(); v++)
+ int r = rows();
+ int c = cols();
+
+ for (int k = 0; k < cols(); k++)
{
- T w = (*this)(i, v);
- if (other(v, j) != 0.f)
+ T w = (*this)(i, k);
+ if (other(k, j) != 0.f)
{
- dotProd += w * other(v, j);
+ dotProd += w * other(k, j);
}
}
}
diff --git a/thirdparty/bullet/LinearMath/btScalar.h b/thirdparty/bullet/LinearMath/btScalar.h
index ba49d6700b..86d94e8974 100644
--- a/thirdparty/bullet/LinearMath/btScalar.h
+++ b/thirdparty/bullet/LinearMath/btScalar.h
@@ -25,13 +25,23 @@ subject to the following restrictions:
#include <float.h>
/* SVN $Revision$ on $Date$ from http://bullet.googlecode.com*/
-#define BT_BULLET_VERSION 288
+#define BT_BULLET_VERSION 289
inline int btGetVersion()
{
return BT_BULLET_VERSION;
}
+inline int btIsDoublePrecision()
+{
+ #ifdef BT_USE_DOUBLE_PRECISION
+ return true;
+ #else
+ return false;
+ #endif
+}
+
+
// The following macro "BT_NOT_EMPTY_FILE" can be put into a file
// in order suppress the MS Visual C++ Linker warning 4221
//
@@ -63,7 +73,12 @@ inline int btGetVersion()
#endif
#ifdef _WIN32
- #if defined(__MINGW32__) || defined(__CYGWIN__) || (defined (_MSC_VER) && _MSC_VER < 1300)
+ #if defined(__GNUC__) // it should handle both MINGW and CYGWIN
+ #define SIMD_FORCE_INLINE __inline__ __attribute__((always_inline))
+ #define ATTRIBUTE_ALIGNED16(a) a __attribute__((aligned(16)))
+ #define ATTRIBUTE_ALIGNED64(a) a __attribute__((aligned(64)))
+ #define ATTRIBUTE_ALIGNED128(a) a __attribute__((aligned(128)))
+ #elif ( defined(_MSC_VER) && _MSC_VER < 1300 )
#define SIMD_FORCE_INLINE inline
#define ATTRIBUTE_ALIGNED16(a) a
#define ATTRIBUTE_ALIGNED64(a) a
@@ -95,11 +110,16 @@ inline int btGetVersion()
#if defined (_M_ARM)
//Do not turn SSE on for ARM (may want to turn on BT_USE_NEON however)
#elif (defined (_WIN32) && (_MSC_VER) && _MSC_VER >= 1400) && (!defined (BT_USE_DOUBLE_PRECISION))
+
+#ifdef __clang__
+#define __BT_DISABLE_SSE__
+#endif
+#ifndef __BT_DISABLE_SSE__
#if _MSC_VER>1400
#define BT_USE_SIMD_VECTOR3
#endif
-
#define BT_USE_SSE
+#endif//__BT_DISABLE_SSE__
#ifdef BT_USE_SSE
#if (_MSC_FULL_VER >= 170050727)//Visual Studio 2012 can compile SSE4/FMA3 (but SSE4/FMA3 is not enabled by default)
diff --git a/thirdparty/bullet/LinearMath/btSerializer.cpp b/thirdparty/bullet/LinearMath/btSerializer.cpp
index 18683c8fa7..068836f2c4 100644
--- a/thirdparty/bullet/LinearMath/btSerializer.cpp
+++ b/thirdparty/bullet/LinearMath/btSerializer.cpp
@@ -1,6 +1,5 @@
-// clang-format off
char sBulletDNAstr[]= {
-char(83),char(68),char(78),char(65),char(78),char(65),char(77),char(69),char(-76),char(1),char(0),char(0),char(109),char(95),char(115),char(105),char(122),char(101),char(0),char(109),
+char(83),char(68),char(78),char(65),char(78),char(65),char(77),char(69),char(-74),char(1),char(0),char(0),char(109),char(95),char(115),char(105),char(122),char(101),char(0),char(109),
char(95),char(99),char(97),char(112),char(97),char(99),char(105),char(116),char(121),char(0),char(42),char(109),char(95),char(100),char(97),char(116),char(97),char(0),char(109),char(95),
char(99),char(111),char(108),char(108),char(105),char(115),char(105),char(111),char(110),char(83),char(104),char(97),char(112),char(101),char(115),char(0),char(109),char(95),char(99),char(111),
char(108),char(108),char(105),char(115),char(105),char(111),char(110),char(79),char(98),char(106),char(101),char(99),char(116),char(115),char(0),char(109),char(95),char(99),char(111),char(110),
@@ -87,606 +86,607 @@ char(101),char(76),char(97),char(116),char(101),char(114),char(97),char(108),cha
char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),char(67),char(97),char(99),char(104),char(101),char(68),char(105),char(115),char(116),
char(97),char(110),char(99),char(101),char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),char(67),char(97),char(99),char(104),char(101),
char(65),char(112),char(112),char(108),char(105),char(101),char(100),char(73),char(109),char(112),char(117),char(108),char(115),char(101),char(91),char(52),char(93),char(0),char(109),char(95),
-char(112),char(111),char(105),char(110),char(116),char(67),char(97),char(99),char(104),char(101),char(67),char(111),char(109),char(98),char(105),char(110),char(101),char(100),char(70),char(114),
-char(105),char(99),char(116),char(105),char(111),char(110),char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),char(67),char(97),char(99),
-char(104),char(101),char(67),char(111),char(109),char(98),char(105),char(110),char(101),char(100),char(82),char(111),char(108),char(108),char(105),char(110),char(103),char(70),char(114),char(105),
-char(99),char(116),char(105),char(111),char(110),char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),char(67),char(97),char(99),char(104),
-char(101),char(67),char(111),char(109),char(98),char(105),char(110),char(101),char(100),char(83),char(112),char(105),char(110),char(110),char(105),char(110),char(103),char(70),char(114),char(105),
-char(99),char(116),char(105),char(111),char(110),char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),char(67),char(97),char(99),char(104),
-char(101),char(67),char(111),char(109),char(98),char(105),char(110),char(101),char(100),char(82),char(101),char(115),char(116),char(105),char(116),char(117),char(116),char(105),char(111),char(110),
-char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),char(67),char(97),char(99),char(104),char(101),char(80),char(97),char(114),char(116),
-char(73),char(100),char(48),char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),char(67),char(97),char(99),char(104),char(101),char(80),
-char(97),char(114),char(116),char(73),char(100),char(49),char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),char(67),char(97),char(99),
-char(104),char(101),char(73),char(110),char(100),char(101),char(120),char(48),char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),char(67),
-char(97),char(99),char(104),char(101),char(73),char(110),char(100),char(101),char(120),char(49),char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),char(110),
-char(116),char(67),char(97),char(99),char(104),char(101),char(67),char(111),char(110),char(116),char(97),char(99),char(116),char(80),char(111),char(105),char(110),char(116),char(70),char(108),
-char(97),char(103),char(115),char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),char(67),char(97),char(99),char(104),char(101),char(65),
-char(112),char(112),char(108),char(105),char(101),char(100),char(73),char(109),char(112),char(117),char(108),char(115),char(101),char(76),char(97),char(116),char(101),char(114),char(97),char(108),
-char(49),char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),char(67),char(97),char(99),char(104),char(101),char(65),char(112),char(112),
-char(108),char(105),char(101),char(100),char(73),char(109),char(112),char(117),char(108),char(115),char(101),char(76),char(97),char(116),char(101),char(114),char(97),char(108),char(50),char(91),
-char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),char(67),char(97),char(99),char(104),char(101),char(67),char(111),char(110),char(116),char(97),
-char(99),char(116),char(77),char(111),char(116),char(105),char(111),char(110),char(49),char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),
-char(67),char(97),char(99),char(104),char(101),char(67),char(111),char(110),char(116),char(97),char(99),char(116),char(77),char(111),char(116),char(105),char(111),char(110),char(50),char(91),
-char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),char(67),char(97),char(99),char(104),char(101),char(67),char(111),char(110),char(116),char(97),
-char(99),char(116),char(67),char(70),char(77),char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),char(67),char(97),char(99),char(104),
-char(101),char(67),char(111),char(109),char(98),char(105),char(110),char(101),char(100),char(67),char(111),char(110),char(116),char(97),char(99),char(116),char(83),char(116),char(105),char(102),
-char(102),char(110),char(101),char(115),char(115),char(49),char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),char(67),char(97),char(99),
-char(104),char(101),char(67),char(111),char(110),char(116),char(97),char(99),char(116),char(69),char(82),char(80),char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),
-char(105),char(110),char(116),char(67),char(97),char(99),char(104),char(101),char(67),char(111),char(109),char(98),char(105),char(110),char(101),char(100),char(67),char(111),char(110),char(116),
-char(97),char(99),char(116),char(68),char(97),char(109),char(112),char(105),char(110),char(103),char(49),char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),
-char(110),char(116),char(67),char(97),char(99),char(104),char(101),char(70),char(114),char(105),char(99),char(116),char(105),char(111),char(110),char(67),char(70),char(77),char(91),char(52),
-char(93),char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),char(67),char(97),char(99),char(104),char(101),char(76),char(105),char(102),char(101),char(84),char(105),
-char(109),char(101),char(91),char(52),char(93),char(0),char(109),char(95),char(110),char(117),char(109),char(67),char(97),char(99),char(104),char(101),char(100),char(80),char(111),char(105),
-char(110),char(116),char(115),char(0),char(109),char(95),char(99),char(111),char(109),char(112),char(97),char(110),char(105),char(111),char(110),char(73),char(100),char(65),char(0),char(109),
-char(95),char(99),char(111),char(109),char(112),char(97),char(110),char(105),char(111),char(110),char(73),char(100),char(66),char(0),char(109),char(95),char(105),char(110),char(100),char(101),
-char(120),char(49),char(97),char(0),char(109),char(95),char(111),char(98),char(106),char(101),char(99),char(116),char(84),char(121),char(112),char(101),char(0),char(109),char(95),char(99),
-char(111),char(110),char(116),char(97),char(99),char(116),char(66),char(114),char(101),char(97),char(107),char(105),char(110),char(103),char(84),char(104),char(114),char(101),char(115),char(104),
-char(111),char(108),char(100),char(0),char(109),char(95),char(99),char(111),char(110),char(116),char(97),char(99),char(116),char(80),char(114),char(111),char(99),char(101),char(115),char(115),
-char(105),char(110),char(103),char(84),char(104),char(114),char(101),char(115),char(104),char(111),char(108),char(100),char(0),char(42),char(109),char(95),char(98),char(111),char(100),char(121),
-char(48),char(0),char(42),char(109),char(95),char(98),char(111),char(100),char(121),char(49),char(0),char(109),char(95),char(103),char(105),char(109),char(112),char(97),char(99),char(116),
-char(83),char(117),char(98),char(84),char(121),char(112),char(101),char(0),char(42),char(109),char(95),char(117),char(110),char(115),char(99),char(97),char(108),char(101),char(100),char(80),
-char(111),char(105),char(110),char(116),char(115),char(70),char(108),char(111),char(97),char(116),char(80),char(116),char(114),char(0),char(42),char(109),char(95),char(117),char(110),char(115),
-char(99),char(97),char(108),char(101),char(100),char(80),char(111),char(105),char(110),char(116),char(115),char(68),char(111),char(117),char(98),char(108),char(101),char(80),char(116),char(114),
-char(0),char(109),char(95),char(110),char(117),char(109),char(85),char(110),char(115),char(99),char(97),char(108),char(101),char(100),char(80),char(111),char(105),char(110),char(116),char(115),
-char(0),char(109),char(95),char(112),char(97),char(100),char(100),char(105),char(110),char(103),char(51),char(91),char(52),char(93),char(0),char(42),char(109),char(95),char(98),char(114),
-char(111),char(97),char(100),char(112),char(104),char(97),char(115),char(101),char(72),char(97),char(110),char(100),char(108),char(101),char(0),char(42),char(109),char(95),char(99),char(111),
-char(108),char(108),char(105),char(115),char(105),char(111),char(110),char(83),char(104),char(97),char(112),char(101),char(0),char(42),char(109),char(95),char(114),char(111),char(111),char(116),
-char(67),char(111),char(108),char(108),char(105),char(115),char(105),char(111),char(110),char(83),char(104),char(97),char(112),char(101),char(0),char(109),char(95),char(119),char(111),char(114),
-char(108),char(100),char(84),char(114),char(97),char(110),char(115),char(102),char(111),char(114),char(109),char(0),char(109),char(95),char(105),char(110),char(116),char(101),char(114),char(112),
-char(111),char(108),char(97),char(116),char(105),char(111),char(110),char(87),char(111),char(114),char(108),char(100),char(84),char(114),char(97),char(110),char(115),char(102),char(111),char(114),
-char(109),char(0),char(109),char(95),char(105),char(110),char(116),char(101),char(114),char(112),char(111),char(108),char(97),char(116),char(105),char(111),char(110),char(76),char(105),char(110),
-char(101),char(97),char(114),char(86),char(101),char(108),char(111),char(99),char(105),char(116),char(121),char(0),char(109),char(95),char(105),char(110),char(116),char(101),char(114),char(112),
-char(111),char(108),char(97),char(116),char(105),char(111),char(110),char(65),char(110),char(103),char(117),char(108),char(97),char(114),char(86),char(101),char(108),char(111),char(99),char(105),
-char(116),char(121),char(0),char(109),char(95),char(97),char(110),char(105),char(115),char(111),char(116),char(114),char(111),char(112),char(105),char(99),char(70),char(114),char(105),char(99),
-char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(100),char(101),char(97),char(99),char(116),char(105),char(118),char(97),char(116),char(105),char(111),char(110),char(84),
-char(105),char(109),char(101),char(0),char(109),char(95),char(102),char(114),char(105),char(99),char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(114),char(111),char(108),
-char(108),char(105),char(110),char(103),char(70),char(114),char(105),char(99),char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(99),char(111),char(110),char(116),char(97),
-char(99),char(116),char(68),char(97),char(109),char(112),char(105),char(110),char(103),char(0),char(109),char(95),char(99),char(111),char(110),char(116),char(97),char(99),char(116),char(83),
-char(116),char(105),char(102),char(102),char(110),char(101),char(115),char(115),char(0),char(109),char(95),char(114),char(101),char(115),char(116),char(105),char(116),char(117),char(116),char(105),
-char(111),char(110),char(0),char(109),char(95),char(104),char(105),char(116),char(70),char(114),char(97),char(99),char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(99),
-char(99),char(100),char(83),char(119),char(101),char(112),char(116),char(83),char(112),char(104),char(101),char(114),char(101),char(82),char(97),char(100),char(105),char(117),char(115),char(0),
-char(109),char(95),char(99),char(99),char(100),char(77),char(111),char(116),char(105),char(111),char(110),char(84),char(104),char(114),char(101),char(115),char(104),char(111),char(108),char(100),
-char(0),char(109),char(95),char(104),char(97),char(115),char(65),char(110),char(105),char(115),char(111),char(116),char(114),char(111),char(112),char(105),char(99),char(70),char(114),char(105),
-char(99),char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(99),char(111),char(108),char(108),char(105),char(115),char(105),char(111),char(110),char(70),char(108),char(97),
-char(103),char(115),char(0),char(109),char(95),char(105),char(115),char(108),char(97),char(110),char(100),char(84),char(97),char(103),char(49),char(0),char(109),char(95),char(99),char(111),
-char(109),char(112),char(97),char(110),char(105),char(111),char(110),char(73),char(100),char(0),char(109),char(95),char(97),char(99),char(116),char(105),char(118),char(97),char(116),char(105),
-char(111),char(110),char(83),char(116),char(97),char(116),char(101),char(49),char(0),char(109),char(95),char(105),char(110),char(116),char(101),char(114),char(110),char(97),char(108),char(84),
-char(121),char(112),char(101),char(0),char(109),char(95),char(99),char(104),char(101),char(99),char(107),char(67),char(111),char(108),char(108),char(105),char(100),char(101),char(87),char(105),
-char(116),char(104),char(0),char(109),char(95),char(99),char(111),char(108),char(108),char(105),char(115),char(105),char(111),char(110),char(70),char(105),char(108),char(116),char(101),char(114),
-char(71),char(114),char(111),char(117),char(112),char(0),char(109),char(95),char(99),char(111),char(108),char(108),char(105),char(115),char(105),char(111),char(110),char(70),char(105),char(108),
-char(116),char(101),char(114),char(77),char(97),char(115),char(107),char(0),char(109),char(95),char(117),char(110),char(105),char(113),char(117),char(101),char(73),char(100),char(0),char(109),
-char(95),char(116),char(97),char(117),char(0),char(109),char(95),char(100),char(97),char(109),char(112),char(105),char(110),char(103),char(0),char(109),char(95),char(116),char(105),char(109),
-char(101),char(83),char(116),char(101),char(112),char(0),char(109),char(95),char(109),char(97),char(120),char(69),char(114),char(114),char(111),char(114),char(82),char(101),char(100),char(117),
-char(99),char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(115),char(111),char(114),char(0),char(109),char(95),char(101),char(114),char(112),char(0),char(109),char(95),
-char(101),char(114),char(112),char(50),char(0),char(109),char(95),char(103),char(108),char(111),char(98),char(97),char(108),char(67),char(102),char(109),char(0),char(109),char(95),char(115),
-char(112),char(108),char(105),char(116),char(73),char(109),char(112),char(117),char(108),char(115),char(101),char(80),char(101),char(110),char(101),char(116),char(114),char(97),char(116),char(105),
-char(111),char(110),char(84),char(104),char(114),char(101),char(115),char(104),char(111),char(108),char(100),char(0),char(109),char(95),char(115),char(112),char(108),char(105),char(116),char(73),
-char(109),char(112),char(117),char(108),char(115),char(101),char(84),char(117),char(114),char(110),char(69),char(114),char(112),char(0),char(109),char(95),char(108),char(105),char(110),char(101),
-char(97),char(114),char(83),char(108),char(111),char(112),char(0),char(109),char(95),char(119),char(97),char(114),char(109),char(115),char(116),char(97),char(114),char(116),char(105),char(110),
-char(103),char(70),char(97),char(99),char(116),char(111),char(114),char(0),char(109),char(95),char(109),char(97),char(120),char(71),char(121),char(114),char(111),char(115),char(99),char(111),
-char(112),char(105),char(99),char(70),char(111),char(114),char(99),char(101),char(0),char(109),char(95),char(115),char(105),char(110),char(103),char(108),char(101),char(65),char(120),char(105),
-char(115),char(82),char(111),char(108),char(108),char(105),char(110),char(103),char(70),char(114),char(105),char(99),char(116),char(105),char(111),char(110),char(84),char(104),char(114),char(101),
-char(115),char(104),char(111),char(108),char(100),char(0),char(109),char(95),char(110),char(117),char(109),char(73),char(116),char(101),char(114),char(97),char(116),char(105),char(111),char(110),
-char(115),char(0),char(109),char(95),char(115),char(111),char(108),char(118),char(101),char(114),char(77),char(111),char(100),char(101),char(0),char(109),char(95),char(114),char(101),char(115),
-char(116),char(105),char(110),char(103),char(67),char(111),char(110),char(116),char(97),char(99),char(116),char(82),char(101),char(115),char(116),char(105),char(116),char(117),char(116),char(105),
-char(111),char(110),char(84),char(104),char(114),char(101),char(115),char(104),char(111),char(108),char(100),char(0),char(109),char(95),char(109),char(105),char(110),char(105),char(109),char(117),
-char(109),char(83),char(111),char(108),char(118),char(101),char(114),char(66),char(97),char(116),char(99),char(104),char(83),char(105),char(122),char(101),char(0),char(109),char(95),char(115),
-char(112),char(108),char(105),char(116),char(73),char(109),char(112),char(117),char(108),char(115),char(101),char(0),char(109),char(95),char(115),char(111),char(108),char(118),char(101),char(114),
-char(73),char(110),char(102),char(111),char(0),char(109),char(95),char(103),char(114),char(97),char(118),char(105),char(116),char(121),char(0),char(109),char(95),char(99),char(111),char(108),
-char(108),char(105),char(115),char(105),char(111),char(110),char(79),char(98),char(106),char(101),char(99),char(116),char(68),char(97),char(116),char(97),char(0),char(109),char(95),char(105),
-char(110),char(118),char(73),char(110),char(101),char(114),char(116),char(105),char(97),char(84),char(101),char(110),char(115),char(111),char(114),char(87),char(111),char(114),char(108),char(100),
-char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(86),char(101),char(108),char(111),char(99),char(105),char(116),char(121),char(0),char(109),char(95),
-char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(86),char(101),char(108),char(111),char(99),char(105),char(116),char(121),char(0),char(109),char(95),char(97),char(110),
-char(103),char(117),char(108),char(97),char(114),char(70),char(97),char(99),char(116),char(111),char(114),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),
-char(70),char(97),char(99),char(116),char(111),char(114),char(0),char(109),char(95),char(103),char(114),char(97),char(118),char(105),char(116),char(121),char(95),char(97),char(99),char(99),
-char(101),char(108),char(101),char(114),char(97),char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(105),char(110),char(118),char(73),char(110),char(101),char(114),char(116),
-char(105),char(97),char(76),char(111),char(99),char(97),char(108),char(0),char(109),char(95),char(116),char(111),char(116),char(97),char(108),char(70),char(111),char(114),char(99),char(101),
-char(0),char(109),char(95),char(116),char(111),char(116),char(97),char(108),char(84),char(111),char(114),char(113),char(117),char(101),char(0),char(109),char(95),char(105),char(110),char(118),
-char(101),char(114),char(115),char(101),char(77),char(97),char(115),char(115),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(68),char(97),char(109),
-char(112),char(105),char(110),char(103),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(68),char(97),char(109),char(112),char(105),char(110),
-char(103),char(0),char(109),char(95),char(97),char(100),char(100),char(105),char(116),char(105),char(111),char(110),char(97),char(108),char(68),char(97),char(109),char(112),char(105),char(110),
-char(103),char(70),char(97),char(99),char(116),char(111),char(114),char(0),char(109),char(95),char(97),char(100),char(100),char(105),char(116),char(105),char(111),char(110),char(97),char(108),
-char(76),char(105),char(110),char(101),char(97),char(114),char(68),char(97),char(109),char(112),char(105),char(110),char(103),char(84),char(104),char(114),char(101),char(115),char(104),char(111),
-char(108),char(100),char(83),char(113),char(114),char(0),char(109),char(95),char(97),char(100),char(100),char(105),char(116),char(105),char(111),char(110),char(97),char(108),char(65),char(110),
-char(103),char(117),char(108),char(97),char(114),char(68),char(97),char(109),char(112),char(105),char(110),char(103),char(84),char(104),char(114),char(101),char(115),char(104),char(111),char(108),
-char(100),char(83),char(113),char(114),char(0),char(109),char(95),char(97),char(100),char(100),char(105),char(116),char(105),char(111),char(110),char(97),char(108),char(65),char(110),char(103),
-char(117),char(108),char(97),char(114),char(68),char(97),char(109),char(112),char(105),char(110),char(103),char(70),char(97),char(99),char(116),char(111),char(114),char(0),char(109),char(95),
-char(108),char(105),char(110),char(101),char(97),char(114),char(83),char(108),char(101),char(101),char(112),char(105),char(110),char(103),char(84),char(104),char(114),char(101),char(115),char(104),
-char(111),char(108),char(100),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(83),char(108),char(101),char(101),char(112),char(105),char(110),
-char(103),char(84),char(104),char(114),char(101),char(115),char(104),char(111),char(108),char(100),char(0),char(109),char(95),char(97),char(100),char(100),char(105),char(116),char(105),char(111),
-char(110),char(97),char(108),char(68),char(97),char(109),char(112),char(105),char(110),char(103),char(0),char(109),char(95),char(110),char(117),char(109),char(67),char(111),char(110),char(115),
-char(116),char(114),char(97),char(105),char(110),char(116),char(82),char(111),char(119),char(115),char(0),char(110),char(117),char(98),char(0),char(42),char(109),char(95),char(114),char(98),
-char(65),char(0),char(42),char(109),char(95),char(114),char(98),char(66),char(0),char(109),char(95),char(117),char(115),char(101),char(114),char(67),char(111),char(110),char(115),char(116),
-char(114),char(97),char(105),char(110),char(116),char(84),char(121),char(112),char(101),char(0),char(109),char(95),char(117),char(115),char(101),char(114),char(67),char(111),char(110),char(115),
-char(116),char(114),char(97),char(105),char(110),char(116),char(73),char(100),char(0),char(109),char(95),char(110),char(101),char(101),char(100),char(115),char(70),char(101),char(101),char(100),
-char(98),char(97),char(99),char(107),char(0),char(109),char(95),char(97),char(112),char(112),char(108),char(105),char(101),char(100),char(73),char(109),char(112),char(117),char(108),char(115),
-char(101),char(0),char(109),char(95),char(100),char(98),char(103),char(68),char(114),char(97),char(119),char(83),char(105),char(122),char(101),char(0),char(109),char(95),char(100),char(105),
-char(115),char(97),char(98),char(108),char(101),char(67),char(111),char(108),char(108),char(105),char(115),char(105),char(111),char(110),char(115),char(66),char(101),char(116),char(119),char(101),
-char(101),char(110),char(76),char(105),char(110),char(107),char(101),char(100),char(66),char(111),char(100),char(105),char(101),char(115),char(0),char(109),char(95),char(111),char(118),char(101),
-char(114),char(114),char(105),char(100),char(101),char(78),char(117),char(109),char(83),char(111),char(108),char(118),char(101),char(114),char(73),char(116),char(101),char(114),char(97),char(116),
-char(105),char(111),char(110),char(115),char(0),char(109),char(95),char(98),char(114),char(101),char(97),char(107),char(105),char(110),char(103),char(73),char(109),char(112),char(117),char(108),
-char(115),char(101),char(84),char(104),char(114),char(101),char(115),char(104),char(111),char(108),char(100),char(0),char(109),char(95),char(105),char(115),char(69),char(110),char(97),char(98),
-char(108),char(101),char(100),char(0),char(112),char(97),char(100),char(100),char(105),char(110),char(103),char(91),char(52),char(93),char(0),char(109),char(95),char(116),char(121),char(112),
-char(101),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(68),char(97),char(116),char(97),char(0),char(109),char(95),char(112),char(105),
-char(118),char(111),char(116),char(73),char(110),char(65),char(0),char(109),char(95),char(112),char(105),char(118),char(111),char(116),char(73),char(110),char(66),char(0),char(109),char(95),
-char(114),char(98),char(65),char(70),char(114),char(97),char(109),char(101),char(0),char(109),char(95),char(114),char(98),char(66),char(70),char(114),char(97),char(109),char(101),char(0),
-char(109),char(95),char(117),char(115),char(101),char(82),char(101),char(102),char(101),char(114),char(101),char(110),char(99),char(101),char(70),char(114),char(97),char(109),char(101),char(65),
-char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(79),char(110),char(108),char(121),char(0),char(109),char(95),char(101),char(110),char(97),
-char(98),char(108),char(101),char(65),char(110),char(103),char(117),char(108),char(97),char(114),char(77),char(111),char(116),char(111),char(114),char(0),char(109),char(95),char(109),char(111),
-char(116),char(111),char(114),char(84),char(97),char(114),char(103),char(101),char(116),char(86),char(101),char(108),char(111),char(99),char(105),char(116),char(121),char(0),char(109),char(95),
-char(109),char(97),char(120),char(77),char(111),char(116),char(111),char(114),char(73),char(109),char(112),char(117),char(108),char(115),char(101),char(0),char(109),char(95),char(108),char(111),
-char(119),char(101),char(114),char(76),char(105),char(109),char(105),char(116),char(0),char(109),char(95),char(117),char(112),char(112),char(101),char(114),char(76),char(105),char(109),char(105),
-char(116),char(0),char(109),char(95),char(108),char(105),char(109),char(105),char(116),char(83),char(111),char(102),char(116),char(110),char(101),char(115),char(115),char(0),char(109),char(95),
-char(98),char(105),char(97),char(115),char(70),char(97),char(99),char(116),char(111),char(114),char(0),char(109),char(95),char(114),char(101),char(108),char(97),char(120),char(97),char(116),
-char(105),char(111),char(110),char(70),char(97),char(99),char(116),char(111),char(114),char(0),char(109),char(95),char(112),char(97),char(100),char(100),char(105),char(110),char(103),char(49),
-char(91),char(52),char(93),char(0),char(109),char(95),char(115),char(119),char(105),char(110),char(103),char(83),char(112),char(97),char(110),char(49),char(0),char(109),char(95),char(115),
-char(119),char(105),char(110),char(103),char(83),char(112),char(97),char(110),char(50),char(0),char(109),char(95),char(116),char(119),char(105),char(115),char(116),char(83),char(112),char(97),
-char(110),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(85),char(112),char(112),char(101),char(114),char(76),char(105),char(109),char(105),char(116),
-char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(76),char(111),char(119),char(101),char(114),char(76),char(105),char(109),char(105),char(116),char(0),
-char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(85),char(112),char(112),char(101),char(114),char(76),char(105),char(109),char(105),char(116),char(0),
-char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(76),char(111),char(119),char(101),char(114),char(76),char(105),char(109),char(105),char(116),char(0),
-char(109),char(95),char(117),char(115),char(101),char(76),char(105),char(110),char(101),char(97),char(114),char(82),char(101),char(102),char(101),char(114),char(101),char(110),char(99),char(101),
-char(70),char(114),char(97),char(109),char(101),char(65),char(0),char(109),char(95),char(117),char(115),char(101),char(79),char(102),char(102),char(115),char(101),char(116),char(70),char(111),
-char(114),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(70),char(114),char(97),char(109),char(101),char(0),char(109),char(95),char(54),
-char(100),char(111),char(102),char(68),char(97),char(116),char(97),char(0),char(109),char(95),char(115),char(112),char(114),char(105),char(110),char(103),char(69),char(110),char(97),char(98),
-char(108),char(101),char(100),char(91),char(54),char(93),char(0),char(109),char(95),char(101),char(113),char(117),char(105),char(108),char(105),char(98),char(114),char(105),char(117),char(109),
-char(80),char(111),char(105),char(110),char(116),char(91),char(54),char(93),char(0),char(109),char(95),char(115),char(112),char(114),char(105),char(110),char(103),char(83),char(116),char(105),
-char(102),char(102),char(110),char(101),char(115),char(115),char(91),char(54),char(93),char(0),char(109),char(95),char(115),char(112),char(114),char(105),char(110),char(103),char(68),char(97),
-char(109),char(112),char(105),char(110),char(103),char(91),char(54),char(93),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(66),char(111),char(117),
-char(110),char(99),char(101),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(83),char(116),char(111),char(112),char(69),char(82),char(80),char(0),
-char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(83),char(116),char(111),char(112),char(67),char(70),char(77),char(0),char(109),char(95),char(108),char(105),
-char(110),char(101),char(97),char(114),char(77),char(111),char(116),char(111),char(114),char(69),char(82),char(80),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),
-char(114),char(77),char(111),char(116),char(111),char(114),char(67),char(70),char(77),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(84),char(97),
-char(114),char(103),char(101),char(116),char(86),char(101),char(108),char(111),char(99),char(105),char(116),char(121),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),
-char(114),char(77),char(97),char(120),char(77),char(111),char(116),char(111),char(114),char(70),char(111),char(114),char(99),char(101),char(0),char(109),char(95),char(108),char(105),char(110),
-char(101),char(97),char(114),char(83),char(101),char(114),char(118),char(111),char(84),char(97),char(114),char(103),char(101),char(116),char(0),char(109),char(95),char(108),char(105),char(110),
-char(101),char(97),char(114),char(83),char(112),char(114),char(105),char(110),char(103),char(83),char(116),char(105),char(102),char(102),char(110),char(101),char(115),char(115),char(0),char(109),
-char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(83),char(112),char(114),char(105),char(110),char(103),char(68),char(97),char(109),char(112),char(105),char(110),char(103),
-char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(69),char(113),char(117),char(105),char(108),char(105),char(98),char(114),char(105),char(117),char(109),
-char(80),char(111),char(105),char(110),char(116),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(69),char(110),char(97),char(98),char(108),char(101),
-char(77),char(111),char(116),char(111),char(114),char(91),char(52),char(93),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(83),char(101),char(114),
-char(118),char(111),char(77),char(111),char(116),char(111),char(114),char(91),char(52),char(93),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(69),
-char(110),char(97),char(98),char(108),char(101),char(83),char(112),char(114),char(105),char(110),char(103),char(91),char(52),char(93),char(0),char(109),char(95),char(108),char(105),char(110),
-char(101),char(97),char(114),char(83),char(112),char(114),char(105),char(110),char(103),char(83),char(116),char(105),char(102),char(102),char(110),char(101),char(115),char(115),char(76),char(105),
-char(109),char(105),char(116),char(101),char(100),char(91),char(52),char(93),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(83),char(112),char(114),
-char(105),char(110),char(103),char(68),char(97),char(109),char(112),char(105),char(110),char(103),char(76),char(105),char(109),char(105),char(116),char(101),char(100),char(91),char(52),char(93),
-char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(66),char(111),char(117),char(110),char(99),char(101),char(0),char(109),char(95),char(97),
-char(110),char(103),char(117),char(108),char(97),char(114),char(83),char(116),char(111),char(112),char(69),char(82),char(80),char(0),char(109),char(95),char(97),char(110),char(103),char(117),
-char(108),char(97),char(114),char(83),char(116),char(111),char(112),char(67),char(70),char(77),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),
-char(77),char(111),char(116),char(111),char(114),char(69),char(82),char(80),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(77),char(111),
-char(116),char(111),char(114),char(67),char(70),char(77),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(84),char(97),char(114),char(103),
-char(101),char(116),char(86),char(101),char(108),char(111),char(99),char(105),char(116),char(121),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),
-char(77),char(97),char(120),char(77),char(111),char(116),char(111),char(114),char(70),char(111),char(114),char(99),char(101),char(0),char(109),char(95),char(97),char(110),char(103),char(117),
-char(108),char(97),char(114),char(83),char(101),char(114),char(118),char(111),char(84),char(97),char(114),char(103),char(101),char(116),char(0),char(109),char(95),char(97),char(110),char(103),
-char(117),char(108),char(97),char(114),char(83),char(112),char(114),char(105),char(110),char(103),char(83),char(116),char(105),char(102),char(102),char(110),char(101),char(115),char(115),char(0),
-char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(83),char(112),char(114),char(105),char(110),char(103),char(68),char(97),char(109),char(112),char(105),
-char(110),char(103),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(69),char(113),char(117),char(105),char(108),char(105),char(98),char(114),
-char(105),char(117),char(109),char(80),char(111),char(105),char(110),char(116),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(69),char(110),
-char(97),char(98),char(108),char(101),char(77),char(111),char(116),char(111),char(114),char(91),char(52),char(93),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),
-char(97),char(114),char(83),char(101),char(114),char(118),char(111),char(77),char(111),char(116),char(111),char(114),char(91),char(52),char(93),char(0),char(109),char(95),char(97),char(110),
-char(103),char(117),char(108),char(97),char(114),char(69),char(110),char(97),char(98),char(108),char(101),char(83),char(112),char(114),char(105),char(110),char(103),char(91),char(52),char(93),
-char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(83),char(112),char(114),char(105),char(110),char(103),char(83),char(116),char(105),char(102),
-char(102),char(110),char(101),char(115),char(115),char(76),char(105),char(109),char(105),char(116),char(101),char(100),char(91),char(52),char(93),char(0),char(109),char(95),char(97),char(110),
-char(103),char(117),char(108),char(97),char(114),char(83),char(112),char(114),char(105),char(110),char(103),char(68),char(97),char(109),char(112),char(105),char(110),char(103),char(76),char(105),
-char(109),char(105),char(116),char(101),char(100),char(91),char(52),char(93),char(0),char(109),char(95),char(114),char(111),char(116),char(97),char(116),char(101),char(79),char(114),char(100),
-char(101),char(114),char(0),char(109),char(95),char(97),char(120),char(105),char(115),char(73),char(110),char(65),char(0),char(109),char(95),char(97),char(120),char(105),char(115),char(73),
-char(110),char(66),char(0),char(109),char(95),char(114),char(97),char(116),char(105),char(111),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(83),
-char(116),char(105),char(102),char(102),char(110),char(101),char(115),char(115),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(83),char(116),
-char(105),char(102),char(102),char(110),char(101),char(115),char(115),char(0),char(109),char(95),char(118),char(111),char(108),char(117),char(109),char(101),char(83),char(116),char(105),char(102),
-char(102),char(110),char(101),char(115),char(115),char(0),char(42),char(109),char(95),char(109),char(97),char(116),char(101),char(114),char(105),char(97),char(108),char(0),char(109),char(95),
-char(112),char(111),char(115),char(105),char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(112),char(114),char(101),char(118),char(105),char(111),char(117),char(115),char(80),
-char(111),char(115),char(105),char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(118),char(101),char(108),char(111),char(99),char(105),char(116),char(121),char(0),char(109),
-char(95),char(97),char(99),char(99),char(117),char(109),char(117),char(108),char(97),char(116),char(101),char(100),char(70),char(111),char(114),char(99),char(101),char(0),char(109),char(95),
-char(110),char(111),char(114),char(109),char(97),char(108),char(0),char(109),char(95),char(97),char(114),char(101),char(97),char(0),char(109),char(95),char(97),char(116),char(116),char(97),
-char(99),char(104),char(0),char(109),char(95),char(110),char(111),char(100),char(101),char(73),char(110),char(100),char(105),char(99),char(101),char(115),char(91),char(50),char(93),char(0),
-char(109),char(95),char(114),char(101),char(115),char(116),char(76),char(101),char(110),char(103),char(116),char(104),char(0),char(109),char(95),char(98),char(98),char(101),char(110),char(100),
-char(105),char(110),char(103),char(0),char(109),char(95),char(110),char(111),char(100),char(101),char(73),char(110),char(100),char(105),char(99),char(101),char(115),char(91),char(51),char(93),
-char(0),char(109),char(95),char(114),char(101),char(115),char(116),char(65),char(114),char(101),char(97),char(0),char(109),char(95),char(99),char(48),char(91),char(52),char(93),char(0),
-char(109),char(95),char(110),char(111),char(100),char(101),char(73),char(110),char(100),char(105),char(99),char(101),char(115),char(91),char(52),char(93),char(0),char(109),char(95),char(114),
-char(101),char(115),char(116),char(86),char(111),char(108),char(117),char(109),char(101),char(0),char(109),char(95),char(99),char(49),char(0),char(109),char(95),char(99),char(50),char(0),
-char(109),char(95),char(99),char(48),char(0),char(109),char(95),char(108),char(111),char(99),char(97),char(108),char(70),char(114),char(97),char(109),char(101),char(0),char(42),char(109),
-char(95),char(114),char(105),char(103),char(105),char(100),char(66),char(111),char(100),char(121),char(0),char(109),char(95),char(110),char(111),char(100),char(101),char(73),char(110),char(100),
-char(101),char(120),char(0),char(109),char(95),char(97),char(101),char(114),char(111),char(77),char(111),char(100),char(101),char(108),char(0),char(109),char(95),char(98),char(97),char(117),
-char(109),char(103),char(97),char(114),char(116),char(101),char(0),char(109),char(95),char(100),char(114),char(97),char(103),char(0),char(109),char(95),char(108),char(105),char(102),char(116),
-char(0),char(109),char(95),char(112),char(114),char(101),char(115),char(115),char(117),char(114),char(101),char(0),char(109),char(95),char(118),char(111),char(108),char(117),char(109),char(101),
-char(0),char(109),char(95),char(100),char(121),char(110),char(97),char(109),char(105),char(99),char(70),char(114),char(105),char(99),char(116),char(105),char(111),char(110),char(0),char(109),
-char(95),char(112),char(111),char(115),char(101),char(77),char(97),char(116),char(99),char(104),char(0),char(109),char(95),char(114),char(105),char(103),char(105),char(100),char(67),char(111),
-char(110),char(116),char(97),char(99),char(116),char(72),char(97),char(114),char(100),char(110),char(101),char(115),char(115),char(0),char(109),char(95),char(107),char(105),char(110),char(101),
-char(116),char(105),char(99),char(67),char(111),char(110),char(116),char(97),char(99),char(116),char(72),char(97),char(114),char(100),char(110),char(101),char(115),char(115),char(0),char(109),
-char(95),char(115),char(111),char(102),char(116),char(67),char(111),char(110),char(116),char(97),char(99),char(116),char(72),char(97),char(114),char(100),char(110),char(101),char(115),char(115),
-char(0),char(109),char(95),char(97),char(110),char(99),char(104),char(111),char(114),char(72),char(97),char(114),char(100),char(110),char(101),char(115),char(115),char(0),char(109),char(95),
-char(115),char(111),char(102),char(116),char(82),char(105),char(103),char(105),char(100),char(67),char(108),char(117),char(115),char(116),char(101),char(114),char(72),char(97),char(114),char(100),
-char(110),char(101),char(115),char(115),char(0),char(109),char(95),char(115),char(111),char(102),char(116),char(75),char(105),char(110),char(101),char(116),char(105),char(99),char(67),char(108),
-char(117),char(115),char(116),char(101),char(114),char(72),char(97),char(114),char(100),char(110),char(101),char(115),char(115),char(0),char(109),char(95),char(115),char(111),char(102),char(116),
-char(83),char(111),char(102),char(116),char(67),char(108),char(117),char(115),char(116),char(101),char(114),char(72),char(97),char(114),char(100),char(110),char(101),char(115),char(115),char(0),
-char(109),char(95),char(115),char(111),char(102),char(116),char(82),char(105),char(103),char(105),char(100),char(67),char(108),char(117),char(115),char(116),char(101),char(114),char(73),char(109),
-char(112),char(117),char(108),char(115),char(101),char(83),char(112),char(108),char(105),char(116),char(0),char(109),char(95),char(115),char(111),char(102),char(116),char(75),char(105),char(110),
-char(101),char(116),char(105),char(99),char(67),char(108),char(117),char(115),char(116),char(101),char(114),char(73),char(109),char(112),char(117),char(108),char(115),char(101),char(83),char(112),
-char(108),char(105),char(116),char(0),char(109),char(95),char(115),char(111),char(102),char(116),char(83),char(111),char(102),char(116),char(67),char(108),char(117),char(115),char(116),char(101),
-char(114),char(73),char(109),char(112),char(117),char(108),char(115),char(101),char(83),char(112),char(108),char(105),char(116),char(0),char(109),char(95),char(109),char(97),char(120),char(86),
-char(111),char(108),char(117),char(109),char(101),char(0),char(109),char(95),char(116),char(105),char(109),char(101),char(83),char(99),char(97),char(108),char(101),char(0),char(109),char(95),
-char(118),char(101),char(108),char(111),char(99),char(105),char(116),char(121),char(73),char(116),char(101),char(114),char(97),char(116),char(105),char(111),char(110),char(115),char(0),char(109),
-char(95),char(112),char(111),char(115),char(105),char(116),char(105),char(111),char(110),char(73),char(116),char(101),char(114),char(97),char(116),char(105),char(111),char(110),char(115),char(0),
-char(109),char(95),char(100),char(114),char(105),char(102),char(116),char(73),char(116),char(101),char(114),char(97),char(116),char(105),char(111),char(110),char(115),char(0),char(109),char(95),
-char(99),char(108),char(117),char(115),char(116),char(101),char(114),char(73),char(116),char(101),char(114),char(97),char(116),char(105),char(111),char(110),char(115),char(0),char(109),char(95),
-char(114),char(111),char(116),char(0),char(109),char(95),char(115),char(99),char(97),char(108),char(101),char(0),char(109),char(95),char(97),char(113),char(113),char(0),char(109),char(95),
-char(99),char(111),char(109),char(0),char(42),char(109),char(95),char(112),char(111),char(115),char(105),char(116),char(105),char(111),char(110),char(115),char(0),char(42),char(109),char(95),
-char(119),char(101),char(105),char(103),char(104),char(116),char(115),char(0),char(109),char(95),char(110),char(117),char(109),char(80),char(111),char(115),char(105),char(116),char(105),char(111),
-char(110),char(115),char(0),char(109),char(95),char(110),char(117),char(109),char(87),char(101),char(105),char(103),char(116),char(115),char(0),char(109),char(95),char(98),char(118),char(111),
-char(108),char(117),char(109),char(101),char(0),char(109),char(95),char(98),char(102),char(114),char(97),char(109),char(101),char(0),char(109),char(95),char(102),char(114),char(97),char(109),
-char(101),char(120),char(102),char(111),char(114),char(109),char(0),char(109),char(95),char(108),char(111),char(99),char(105),char(105),char(0),char(109),char(95),char(105),char(110),char(118),
-char(119),char(105),char(0),char(109),char(95),char(118),char(105),char(109),char(112),char(117),char(108),char(115),char(101),char(115),char(91),char(50),char(93),char(0),char(109),char(95),
-char(100),char(105),char(109),char(112),char(117),char(108),char(115),char(101),char(115),char(91),char(50),char(93),char(0),char(109),char(95),char(108),char(118),char(0),char(109),char(95),
-char(97),char(118),char(0),char(42),char(109),char(95),char(102),char(114),char(97),char(109),char(101),char(114),char(101),char(102),char(115),char(0),char(42),char(109),char(95),char(110),
-char(111),char(100),char(101),char(73),char(110),char(100),char(105),char(99),char(101),char(115),char(0),char(42),char(109),char(95),char(109),char(97),char(115),char(115),char(101),char(115),
-char(0),char(109),char(95),char(110),char(117),char(109),char(70),char(114),char(97),char(109),char(101),char(82),char(101),char(102),char(115),char(0),char(109),char(95),char(110),char(117),
-char(109),char(78),char(111),char(100),char(101),char(115),char(0),char(109),char(95),char(110),char(117),char(109),char(77),char(97),char(115),char(115),char(101),char(115),char(0),char(109),
-char(95),char(105),char(100),char(109),char(97),char(115),char(115),char(0),char(109),char(95),char(105),char(109),char(97),char(115),char(115),char(0),char(109),char(95),char(110),char(118),
-char(105),char(109),char(112),char(117),char(108),char(115),char(101),char(115),char(0),char(109),char(95),char(110),char(100),char(105),char(109),char(112),char(117),char(108),char(115),char(101),
-char(115),char(0),char(109),char(95),char(110),char(100),char(97),char(109),char(112),char(105),char(110),char(103),char(0),char(109),char(95),char(108),char(100),char(97),char(109),char(112),
-char(105),char(110),char(103),char(0),char(109),char(95),char(97),char(100),char(97),char(109),char(112),char(105),char(110),char(103),char(0),char(109),char(95),char(109),char(97),char(116),
-char(99),char(104),char(105),char(110),char(103),char(0),char(109),char(95),char(109),char(97),char(120),char(83),char(101),char(108),char(102),char(67),char(111),char(108),char(108),char(105),
-char(115),char(105),char(111),char(110),char(73),char(109),char(112),char(117),char(108),char(115),char(101),char(0),char(109),char(95),char(115),char(101),char(108),char(102),char(67),char(111),
-char(108),char(108),char(105),char(115),char(105),char(111),char(110),char(73),char(109),char(112),char(117),char(108),char(115),char(101),char(70),char(97),char(99),char(116),char(111),char(114),
-char(0),char(109),char(95),char(99),char(111),char(110),char(116),char(97),char(105),char(110),char(115),char(65),char(110),char(99),char(104),char(111),char(114),char(0),char(109),char(95),
-char(99),char(111),char(108),char(108),char(105),char(100),char(101),char(0),char(109),char(95),char(99),char(108),char(117),char(115),char(116),char(101),char(114),char(73),char(110),char(100),
-char(101),char(120),char(0),char(42),char(109),char(95),char(98),char(111),char(100),char(121),char(65),char(0),char(42),char(109),char(95),char(98),char(111),char(100),char(121),char(66),
-char(0),char(109),char(95),char(114),char(101),char(102),char(115),char(91),char(50),char(93),char(0),char(109),char(95),char(99),char(102),char(109),char(0),char(109),char(95),char(115),
-char(112),char(108),char(105),char(116),char(0),char(109),char(95),char(100),char(101),char(108),char(101),char(116),char(101),char(0),char(109),char(95),char(114),char(101),char(108),char(80),
-char(111),char(115),char(105),char(116),char(105),char(111),char(110),char(91),char(50),char(93),char(0),char(109),char(95),char(98),char(111),char(100),char(121),char(65),char(116),char(121),
-char(112),char(101),char(0),char(109),char(95),char(98),char(111),char(100),char(121),char(66),char(116),char(121),char(112),char(101),char(0),char(109),char(95),char(106),char(111),char(105),
-char(110),char(116),char(84),char(121),char(112),char(101),char(0),char(42),char(109),char(95),char(112),char(111),char(115),char(101),char(0),char(42),char(42),char(109),char(95),char(109),
-char(97),char(116),char(101),char(114),char(105),char(97),char(108),char(115),char(0),char(42),char(109),char(95),char(110),char(111),char(100),char(101),char(115),char(0),char(42),char(109),
-char(95),char(108),char(105),char(110),char(107),char(115),char(0),char(42),char(109),char(95),char(102),char(97),char(99),char(101),char(115),char(0),char(42),char(109),char(95),char(116),
-char(101),char(116),char(114),char(97),char(104),char(101),char(100),char(114),char(97),char(0),char(42),char(109),char(95),char(97),char(110),char(99),char(104),char(111),char(114),char(115),
-char(0),char(42),char(109),char(95),char(99),char(108),char(117),char(115),char(116),char(101),char(114),char(115),char(0),char(42),char(109),char(95),char(106),char(111),char(105),char(110),
-char(116),char(115),char(0),char(109),char(95),char(110),char(117),char(109),char(77),char(97),char(116),char(101),char(114),char(105),char(97),char(108),char(115),char(0),char(109),char(95),
-char(110),char(117),char(109),char(76),char(105),char(110),char(107),char(115),char(0),char(109),char(95),char(110),char(117),char(109),char(70),char(97),char(99),char(101),char(115),char(0),
-char(109),char(95),char(110),char(117),char(109),char(84),char(101),char(116),char(114),char(97),char(104),char(101),char(100),char(114),char(97),char(0),char(109),char(95),char(110),char(117),
-char(109),char(65),char(110),char(99),char(104),char(111),char(114),char(115),char(0),char(109),char(95),char(110),char(117),char(109),char(67),char(108),char(117),char(115),char(116),char(101),
-char(114),char(115),char(0),char(109),char(95),char(110),char(117),char(109),char(74),char(111),char(105),char(110),char(116),char(115),char(0),char(109),char(95),char(99),char(111),char(110),
-char(102),char(105),char(103),char(0),char(109),char(95),char(122),char(101),char(114),char(111),char(82),char(111),char(116),char(80),char(97),char(114),char(101),char(110),char(116),char(84),
-char(111),char(84),char(104),char(105),char(115),char(0),char(109),char(95),char(112),char(97),char(114),char(101),char(110),char(116),char(67),char(111),char(109),char(84),char(111),char(84),
-char(104),char(105),char(115),char(80),char(105),char(118),char(111),char(116),char(79),char(102),char(102),char(115),char(101),char(116),char(0),char(109),char(95),char(116),char(104),char(105),
-char(115),char(80),char(105),char(118),char(111),char(116),char(84),char(111),char(84),char(104),char(105),char(115),char(67),char(111),char(109),char(79),char(102),char(102),char(115),char(101),
-char(116),char(0),char(109),char(95),char(106),char(111),char(105),char(110),char(116),char(65),char(120),char(105),char(115),char(84),char(111),char(112),char(91),char(54),char(93),char(0),
-char(109),char(95),char(106),char(111),char(105),char(110),char(116),char(65),char(120),char(105),char(115),char(66),char(111),char(116),char(116),char(111),char(109),char(91),char(54),char(93),
-char(0),char(109),char(95),char(108),char(105),char(110),char(107),char(73),char(110),char(101),char(114),char(116),char(105),char(97),char(0),char(109),char(95),char(97),char(98),char(115),
-char(70),char(114),char(97),char(109),char(101),char(84),char(111),char(116),char(86),char(101),char(108),char(111),char(99),char(105),char(116),char(121),char(84),char(111),char(112),char(0),
-char(109),char(95),char(97),char(98),char(115),char(70),char(114),char(97),char(109),char(101),char(84),char(111),char(116),char(86),char(101),char(108),char(111),char(99),char(105),char(116),
-char(121),char(66),char(111),char(116),char(116),char(111),char(109),char(0),char(109),char(95),char(97),char(98),char(115),char(70),char(114),char(97),char(109),char(101),char(76),char(111),
-char(99),char(86),char(101),char(108),char(111),char(99),char(105),char(116),char(121),char(84),char(111),char(112),char(0),char(109),char(95),char(97),char(98),char(115),char(70),char(114),
-char(97),char(109),char(101),char(76),char(111),char(99),char(86),char(101),char(108),char(111),char(99),char(105),char(116),char(121),char(66),char(111),char(116),char(116),char(111),char(109),
-char(0),char(109),char(95),char(108),char(105),char(110),char(107),char(77),char(97),char(115),char(115),char(0),char(109),char(95),char(112),char(97),char(114),char(101),char(110),char(116),
-char(73),char(110),char(100),char(101),char(120),char(0),char(109),char(95),char(100),char(111),char(102),char(67),char(111),char(117),char(110),char(116),char(0),char(109),char(95),char(112),
-char(111),char(115),char(86),char(97),char(114),char(67),char(111),char(117),char(110),char(116),char(0),char(109),char(95),char(106),char(111),char(105),char(110),char(116),char(80),char(111),
-char(115),char(91),char(55),char(93),char(0),char(109),char(95),char(106),char(111),char(105),char(110),char(116),char(86),char(101),char(108),char(91),char(54),char(93),char(0),char(109),
-char(95),char(106),char(111),char(105),char(110),char(116),char(84),char(111),char(114),char(113),char(117),char(101),char(91),char(54),char(93),char(0),char(109),char(95),char(106),char(111),
-char(105),char(110),char(116),char(68),char(97),char(109),char(112),char(105),char(110),char(103),char(0),char(109),char(95),char(106),char(111),char(105),char(110),char(116),char(70),char(114),
-char(105),char(99),char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(106),char(111),char(105),char(110),char(116),char(76),char(111),char(119),char(101),char(114),char(76),
-char(105),char(109),char(105),char(116),char(0),char(109),char(95),char(106),char(111),char(105),char(110),char(116),char(85),char(112),char(112),char(101),char(114),char(76),char(105),char(109),
-char(105),char(116),char(0),char(109),char(95),char(106),char(111),char(105),char(110),char(116),char(77),char(97),char(120),char(70),char(111),char(114),char(99),char(101),char(0),char(109),
-char(95),char(106),char(111),char(105),char(110),char(116),char(77),char(97),char(120),char(86),char(101),char(108),char(111),char(99),char(105),char(116),char(121),char(0),char(42),char(109),
-char(95),char(108),char(105),char(110),char(107),char(78),char(97),char(109),char(101),char(0),char(42),char(109),char(95),char(106),char(111),char(105),char(110),char(116),char(78),char(97),
-char(109),char(101),char(0),char(42),char(109),char(95),char(108),char(105),char(110),char(107),char(67),char(111),char(108),char(108),char(105),char(100),char(101),char(114),char(0),char(42),
-char(109),char(95),char(112),char(97),char(100),char(100),char(105),char(110),char(103),char(80),char(116),char(114),char(0),char(109),char(95),char(98),char(97),char(115),char(101),char(87),
-char(111),char(114),char(108),char(100),char(80),char(111),char(115),char(105),char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(98),char(97),char(115),char(101),char(87),
-char(111),char(114),char(108),char(100),char(79),char(114),char(105),char(101),char(110),char(116),char(97),char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(98),char(97),
-char(115),char(101),char(76),char(105),char(110),char(101),char(97),char(114),char(86),char(101),char(108),char(111),char(99),char(105),char(116),char(121),char(0),char(109),char(95),char(98),
-char(97),char(115),char(101),char(65),char(110),char(103),char(117),char(108),char(97),char(114),char(86),char(101),char(108),char(111),char(99),char(105),char(116),char(121),char(0),char(109),
-char(95),char(98),char(97),char(115),char(101),char(73),char(110),char(101),char(114),char(116),char(105),char(97),char(0),char(109),char(95),char(98),char(97),char(115),char(101),char(77),
-char(97),char(115),char(115),char(0),char(42),char(109),char(95),char(98),char(97),char(115),char(101),char(78),char(97),char(109),char(101),char(0),char(42),char(109),char(95),char(98),
-char(97),char(115),char(101),char(67),char(111),char(108),char(108),char(105),char(100),char(101),char(114),char(0),char(109),char(95),char(99),char(111),char(108),char(79),char(98),char(106),
-char(68),char(97),char(116),char(97),char(0),char(42),char(109),char(95),char(109),char(117),char(108),char(116),char(105),char(66),char(111),char(100),char(121),char(0),char(109),char(95),
-char(108),char(105),char(110),char(107),char(0),char(0),char(0),char(0),char(84),char(89),char(80),char(69),char(99),char(0),char(0),char(0),char(99),char(104),char(97),char(114),
-char(0),char(117),char(99),char(104),char(97),char(114),char(0),char(115),char(104),char(111),char(114),char(116),char(0),char(117),char(115),char(104),char(111),char(114),char(116),char(0),
-char(105),char(110),char(116),char(0),char(108),char(111),char(110),char(103),char(0),char(117),char(108),char(111),char(110),char(103),char(0),char(102),char(108),char(111),char(97),char(116),
-char(0),char(100),char(111),char(117),char(98),char(108),char(101),char(0),char(118),char(111),char(105),char(100),char(0),char(80),char(111),char(105),char(110),char(116),char(101),char(114),
-char(65),char(114),char(114),char(97),char(121),char(0),char(98),char(116),char(80),char(104),char(121),char(115),char(105),char(99),char(115),char(83),char(121),char(115),char(116),char(101),
-char(109),char(0),char(76),char(105),char(115),char(116),char(66),char(97),char(115),char(101),char(0),char(98),char(116),char(86),char(101),char(99),char(116),char(111),char(114),char(51),
-char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(86),char(101),char(99),char(116),char(111),char(114),char(51),char(68),
-char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(81),char(117),char(97),char(116),char(101),char(114),char(110),char(105),
-char(111),char(110),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(81),char(117),char(97),char(116),char(101),char(114),
-char(110),char(105),char(111),char(110),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(77),char(97),char(116),
-char(114),char(105),char(120),char(51),char(120),char(51),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(77),char(97),
-char(116),char(114),char(105),char(120),char(51),char(120),char(51),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),
-char(84),char(114),char(97),char(110),char(115),char(102),char(111),char(114),char(109),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),
-char(116),char(84),char(114),char(97),char(110),char(115),char(102),char(111),char(114),char(109),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),
-char(0),char(98),char(116),char(66),char(118),char(104),char(83),char(117),char(98),char(116),char(114),char(101),char(101),char(73),char(110),char(102),char(111),char(68),char(97),char(116),
+char(112),char(111),char(105),char(110),char(116),char(67),char(97),char(99),char(104),char(101),char(80),char(114),char(101),char(118),char(82),char(72),char(83),char(91),char(52),char(93),
+char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),char(67),char(97),char(99),char(104),char(101),char(67),char(111),char(109),char(98),char(105),char(110),char(101),
+char(100),char(70),char(114),char(105),char(99),char(116),char(105),char(111),char(110),char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),
+char(67),char(97),char(99),char(104),char(101),char(67),char(111),char(109),char(98),char(105),char(110),char(101),char(100),char(82),char(111),char(108),char(108),char(105),char(110),char(103),
+char(70),char(114),char(105),char(99),char(116),char(105),char(111),char(110),char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),char(67),
+char(97),char(99),char(104),char(101),char(67),char(111),char(109),char(98),char(105),char(110),char(101),char(100),char(83),char(112),char(105),char(110),char(110),char(105),char(110),char(103),
+char(70),char(114),char(105),char(99),char(116),char(105),char(111),char(110),char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),char(67),
+char(97),char(99),char(104),char(101),char(67),char(111),char(109),char(98),char(105),char(110),char(101),char(100),char(82),char(101),char(115),char(116),char(105),char(116),char(117),char(116),
+char(105),char(111),char(110),char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),char(67),char(97),char(99),char(104),char(101),char(80),
+char(97),char(114),char(116),char(73),char(100),char(48),char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),char(67),char(97),char(99),
+char(104),char(101),char(80),char(97),char(114),char(116),char(73),char(100),char(49),char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),
+char(67),char(97),char(99),char(104),char(101),char(73),char(110),char(100),char(101),char(120),char(48),char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),
+char(110),char(116),char(67),char(97),char(99),char(104),char(101),char(73),char(110),char(100),char(101),char(120),char(49),char(91),char(52),char(93),char(0),char(109),char(95),char(112),
+char(111),char(105),char(110),char(116),char(67),char(97),char(99),char(104),char(101),char(67),char(111),char(110),char(116),char(97),char(99),char(116),char(80),char(111),char(105),char(110),
+char(116),char(70),char(108),char(97),char(103),char(115),char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),char(67),char(97),char(99),
+char(104),char(101),char(65),char(112),char(112),char(108),char(105),char(101),char(100),char(73),char(109),char(112),char(117),char(108),char(115),char(101),char(76),char(97),char(116),char(101),
+char(114),char(97),char(108),char(49),char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),char(67),char(97),char(99),char(104),char(101),
+char(65),char(112),char(112),char(108),char(105),char(101),char(100),char(73),char(109),char(112),char(117),char(108),char(115),char(101),char(76),char(97),char(116),char(101),char(114),char(97),
+char(108),char(50),char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),char(67),char(97),char(99),char(104),char(101),char(67),char(111),
+char(110),char(116),char(97),char(99),char(116),char(77),char(111),char(116),char(105),char(111),char(110),char(49),char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),
+char(105),char(110),char(116),char(67),char(97),char(99),char(104),char(101),char(67),char(111),char(110),char(116),char(97),char(99),char(116),char(77),char(111),char(116),char(105),char(111),
+char(110),char(50),char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),char(67),char(97),char(99),char(104),char(101),char(67),char(111),
+char(110),char(116),char(97),char(99),char(116),char(67),char(70),char(77),char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),char(67),
+char(97),char(99),char(104),char(101),char(67),char(111),char(109),char(98),char(105),char(110),char(101),char(100),char(67),char(111),char(110),char(116),char(97),char(99),char(116),char(83),
+char(116),char(105),char(102),char(102),char(110),char(101),char(115),char(115),char(49),char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),
+char(67),char(97),char(99),char(104),char(101),char(67),char(111),char(110),char(116),char(97),char(99),char(116),char(69),char(82),char(80),char(91),char(52),char(93),char(0),char(109),
+char(95),char(112),char(111),char(105),char(110),char(116),char(67),char(97),char(99),char(104),char(101),char(67),char(111),char(109),char(98),char(105),char(110),char(101),char(100),char(67),
+char(111),char(110),char(116),char(97),char(99),char(116),char(68),char(97),char(109),char(112),char(105),char(110),char(103),char(49),char(91),char(52),char(93),char(0),char(109),char(95),
+char(112),char(111),char(105),char(110),char(116),char(67),char(97),char(99),char(104),char(101),char(70),char(114),char(105),char(99),char(116),char(105),char(111),char(110),char(67),char(70),
+char(77),char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),char(67),char(97),char(99),char(104),char(101),char(76),char(105),char(102),
+char(101),char(84),char(105),char(109),char(101),char(91),char(52),char(93),char(0),char(109),char(95),char(110),char(117),char(109),char(67),char(97),char(99),char(104),char(101),char(100),
+char(80),char(111),char(105),char(110),char(116),char(115),char(0),char(109),char(95),char(99),char(111),char(109),char(112),char(97),char(110),char(105),char(111),char(110),char(73),char(100),
+char(65),char(0),char(109),char(95),char(99),char(111),char(109),char(112),char(97),char(110),char(105),char(111),char(110),char(73),char(100),char(66),char(0),char(109),char(95),char(105),
+char(110),char(100),char(101),char(120),char(49),char(97),char(0),char(109),char(95),char(111),char(98),char(106),char(101),char(99),char(116),char(84),char(121),char(112),char(101),char(0),
+char(109),char(95),char(99),char(111),char(110),char(116),char(97),char(99),char(116),char(66),char(114),char(101),char(97),char(107),char(105),char(110),char(103),char(84),char(104),char(114),
+char(101),char(115),char(104),char(111),char(108),char(100),char(0),char(109),char(95),char(99),char(111),char(110),char(116),char(97),char(99),char(116),char(80),char(114),char(111),char(99),
+char(101),char(115),char(115),char(105),char(110),char(103),char(84),char(104),char(114),char(101),char(115),char(104),char(111),char(108),char(100),char(0),char(42),char(109),char(95),char(98),
+char(111),char(100),char(121),char(48),char(0),char(42),char(109),char(95),char(98),char(111),char(100),char(121),char(49),char(0),char(109),char(95),char(103),char(105),char(109),char(112),
+char(97),char(99),char(116),char(83),char(117),char(98),char(84),char(121),char(112),char(101),char(0),char(42),char(109),char(95),char(117),char(110),char(115),char(99),char(97),char(108),
+char(101),char(100),char(80),char(111),char(105),char(110),char(116),char(115),char(70),char(108),char(111),char(97),char(116),char(80),char(116),char(114),char(0),char(42),char(109),char(95),
+char(117),char(110),char(115),char(99),char(97),char(108),char(101),char(100),char(80),char(111),char(105),char(110),char(116),char(115),char(68),char(111),char(117),char(98),char(108),char(101),
+char(80),char(116),char(114),char(0),char(109),char(95),char(110),char(117),char(109),char(85),char(110),char(115),char(99),char(97),char(108),char(101),char(100),char(80),char(111),char(105),
+char(110),char(116),char(115),char(0),char(109),char(95),char(112),char(97),char(100),char(100),char(105),char(110),char(103),char(51),char(91),char(52),char(93),char(0),char(42),char(109),
+char(95),char(98),char(114),char(111),char(97),char(100),char(112),char(104),char(97),char(115),char(101),char(72),char(97),char(110),char(100),char(108),char(101),char(0),char(42),char(109),
+char(95),char(99),char(111),char(108),char(108),char(105),char(115),char(105),char(111),char(110),char(83),char(104),char(97),char(112),char(101),char(0),char(42),char(109),char(95),char(114),
+char(111),char(111),char(116),char(67),char(111),char(108),char(108),char(105),char(115),char(105),char(111),char(110),char(83),char(104),char(97),char(112),char(101),char(0),char(109),char(95),
+char(119),char(111),char(114),char(108),char(100),char(84),char(114),char(97),char(110),char(115),char(102),char(111),char(114),char(109),char(0),char(109),char(95),char(105),char(110),char(116),
+char(101),char(114),char(112),char(111),char(108),char(97),char(116),char(105),char(111),char(110),char(87),char(111),char(114),char(108),char(100),char(84),char(114),char(97),char(110),char(115),
+char(102),char(111),char(114),char(109),char(0),char(109),char(95),char(105),char(110),char(116),char(101),char(114),char(112),char(111),char(108),char(97),char(116),char(105),char(111),char(110),
+char(76),char(105),char(110),char(101),char(97),char(114),char(86),char(101),char(108),char(111),char(99),char(105),char(116),char(121),char(0),char(109),char(95),char(105),char(110),char(116),
+char(101),char(114),char(112),char(111),char(108),char(97),char(116),char(105),char(111),char(110),char(65),char(110),char(103),char(117),char(108),char(97),char(114),char(86),char(101),char(108),
+char(111),char(99),char(105),char(116),char(121),char(0),char(109),char(95),char(97),char(110),char(105),char(115),char(111),char(116),char(114),char(111),char(112),char(105),char(99),char(70),
+char(114),char(105),char(99),char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(100),char(101),char(97),char(99),char(116),char(105),char(118),char(97),char(116),char(105),
+char(111),char(110),char(84),char(105),char(109),char(101),char(0),char(109),char(95),char(102),char(114),char(105),char(99),char(116),char(105),char(111),char(110),char(0),char(109),char(95),
+char(114),char(111),char(108),char(108),char(105),char(110),char(103),char(70),char(114),char(105),char(99),char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(99),char(111),
+char(110),char(116),char(97),char(99),char(116),char(68),char(97),char(109),char(112),char(105),char(110),char(103),char(0),char(109),char(95),char(99),char(111),char(110),char(116),char(97),
+char(99),char(116),char(83),char(116),char(105),char(102),char(102),char(110),char(101),char(115),char(115),char(0),char(109),char(95),char(114),char(101),char(115),char(116),char(105),char(116),
+char(117),char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(104),char(105),char(116),char(70),char(114),char(97),char(99),char(116),char(105),char(111),char(110),char(0),
+char(109),char(95),char(99),char(99),char(100),char(83),char(119),char(101),char(112),char(116),char(83),char(112),char(104),char(101),char(114),char(101),char(82),char(97),char(100),char(105),
+char(117),char(115),char(0),char(109),char(95),char(99),char(99),char(100),char(77),char(111),char(116),char(105),char(111),char(110),char(84),char(104),char(114),char(101),char(115),char(104),
+char(111),char(108),char(100),char(0),char(109),char(95),char(104),char(97),char(115),char(65),char(110),char(105),char(115),char(111),char(116),char(114),char(111),char(112),char(105),char(99),
+char(70),char(114),char(105),char(99),char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(99),char(111),char(108),char(108),char(105),char(115),char(105),char(111),char(110),
+char(70),char(108),char(97),char(103),char(115),char(0),char(109),char(95),char(105),char(115),char(108),char(97),char(110),char(100),char(84),char(97),char(103),char(49),char(0),char(109),
+char(95),char(99),char(111),char(109),char(112),char(97),char(110),char(105),char(111),char(110),char(73),char(100),char(0),char(109),char(95),char(97),char(99),char(116),char(105),char(118),
+char(97),char(116),char(105),char(111),char(110),char(83),char(116),char(97),char(116),char(101),char(49),char(0),char(109),char(95),char(105),char(110),char(116),char(101),char(114),char(110),
+char(97),char(108),char(84),char(121),char(112),char(101),char(0),char(109),char(95),char(99),char(104),char(101),char(99),char(107),char(67),char(111),char(108),char(108),char(105),char(100),
+char(101),char(87),char(105),char(116),char(104),char(0),char(109),char(95),char(99),char(111),char(108),char(108),char(105),char(115),char(105),char(111),char(110),char(70),char(105),char(108),
+char(116),char(101),char(114),char(71),char(114),char(111),char(117),char(112),char(0),char(109),char(95),char(99),char(111),char(108),char(108),char(105),char(115),char(105),char(111),char(110),
+char(70),char(105),char(108),char(116),char(101),char(114),char(77),char(97),char(115),char(107),char(0),char(109),char(95),char(117),char(110),char(105),char(113),char(117),char(101),char(73),
+char(100),char(0),char(109),char(95),char(116),char(97),char(117),char(0),char(109),char(95),char(100),char(97),char(109),char(112),char(105),char(110),char(103),char(0),char(109),char(95),
+char(116),char(105),char(109),char(101),char(83),char(116),char(101),char(112),char(0),char(109),char(95),char(109),char(97),char(120),char(69),char(114),char(114),char(111),char(114),char(82),
+char(101),char(100),char(117),char(99),char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(115),char(111),char(114),char(0),char(109),char(95),char(101),char(114),char(112),
+char(0),char(109),char(95),char(101),char(114),char(112),char(50),char(0),char(109),char(95),char(103),char(108),char(111),char(98),char(97),char(108),char(67),char(102),char(109),char(0),
+char(109),char(95),char(115),char(112),char(108),char(105),char(116),char(73),char(109),char(112),char(117),char(108),char(115),char(101),char(80),char(101),char(110),char(101),char(116),char(114),
+char(97),char(116),char(105),char(111),char(110),char(84),char(104),char(114),char(101),char(115),char(104),char(111),char(108),char(100),char(0),char(109),char(95),char(115),char(112),char(108),
+char(105),char(116),char(73),char(109),char(112),char(117),char(108),char(115),char(101),char(84),char(117),char(114),char(110),char(69),char(114),char(112),char(0),char(109),char(95),char(108),
+char(105),char(110),char(101),char(97),char(114),char(83),char(108),char(111),char(112),char(0),char(109),char(95),char(119),char(97),char(114),char(109),char(115),char(116),char(97),char(114),
+char(116),char(105),char(110),char(103),char(70),char(97),char(99),char(116),char(111),char(114),char(0),char(109),char(95),char(97),char(114),char(116),char(105),char(99),char(117),char(108),
+char(97),char(116),char(101),char(100),char(87),char(97),char(114),char(109),char(115),char(116),char(97),char(114),char(116),char(105),char(110),char(103),char(70),char(97),char(99),char(116),
+char(111),char(114),char(0),char(109),char(95),char(109),char(97),char(120),char(71),char(121),char(114),char(111),char(115),char(99),char(111),char(112),char(105),char(99),char(70),char(111),
+char(114),char(99),char(101),char(0),char(109),char(95),char(115),char(105),char(110),char(103),char(108),char(101),char(65),char(120),char(105),char(115),char(82),char(111),char(108),char(108),
+char(105),char(110),char(103),char(70),char(114),char(105),char(99),char(116),char(105),char(111),char(110),char(84),char(104),char(114),char(101),char(115),char(104),char(111),char(108),char(100),
+char(0),char(109),char(95),char(110),char(117),char(109),char(73),char(116),char(101),char(114),char(97),char(116),char(105),char(111),char(110),char(115),char(0),char(109),char(95),char(115),
+char(111),char(108),char(118),char(101),char(114),char(77),char(111),char(100),char(101),char(0),char(109),char(95),char(114),char(101),char(115),char(116),char(105),char(110),char(103),char(67),
+char(111),char(110),char(116),char(97),char(99),char(116),char(82),char(101),char(115),char(116),char(105),char(116),char(117),char(116),char(105),char(111),char(110),char(84),char(104),char(114),
+char(101),char(115),char(104),char(111),char(108),char(100),char(0),char(109),char(95),char(109),char(105),char(110),char(105),char(109),char(117),char(109),char(83),char(111),char(108),char(118),
+char(101),char(114),char(66),char(97),char(116),char(99),char(104),char(83),char(105),char(122),char(101),char(0),char(109),char(95),char(115),char(112),char(108),char(105),char(116),char(73),
+char(109),char(112),char(117),char(108),char(115),char(101),char(0),char(109),char(95),char(115),char(111),char(108),char(118),char(101),char(114),char(73),char(110),char(102),char(111),char(0),
+char(109),char(95),char(103),char(114),char(97),char(118),char(105),char(116),char(121),char(0),char(109),char(95),char(99),char(111),char(108),char(108),char(105),char(115),char(105),char(111),
+char(110),char(79),char(98),char(106),char(101),char(99),char(116),char(68),char(97),char(116),char(97),char(0),char(109),char(95),char(105),char(110),char(118),char(73),char(110),char(101),
+char(114),char(116),char(105),char(97),char(84),char(101),char(110),char(115),char(111),char(114),char(87),char(111),char(114),char(108),char(100),char(0),char(109),char(95),char(108),char(105),
+char(110),char(101),char(97),char(114),char(86),char(101),char(108),char(111),char(99),char(105),char(116),char(121),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),
+char(97),char(114),char(86),char(101),char(108),char(111),char(99),char(105),char(116),char(121),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),
+char(70),char(97),char(99),char(116),char(111),char(114),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(70),char(97),char(99),char(116),char(111),
+char(114),char(0),char(109),char(95),char(103),char(114),char(97),char(118),char(105),char(116),char(121),char(95),char(97),char(99),char(99),char(101),char(108),char(101),char(114),char(97),
+char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(105),char(110),char(118),char(73),char(110),char(101),char(114),char(116),char(105),char(97),char(76),char(111),char(99),
+char(97),char(108),char(0),char(109),char(95),char(116),char(111),char(116),char(97),char(108),char(70),char(111),char(114),char(99),char(101),char(0),char(109),char(95),char(116),char(111),
+char(116),char(97),char(108),char(84),char(111),char(114),char(113),char(117),char(101),char(0),char(109),char(95),char(105),char(110),char(118),char(101),char(114),char(115),char(101),char(77),
+char(97),char(115),char(115),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(68),char(97),char(109),char(112),char(105),char(110),char(103),char(0),
+char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(68),char(97),char(109),char(112),char(105),char(110),char(103),char(0),char(109),char(95),char(97),
+char(100),char(100),char(105),char(116),char(105),char(111),char(110),char(97),char(108),char(68),char(97),char(109),char(112),char(105),char(110),char(103),char(70),char(97),char(99),char(116),
+char(111),char(114),char(0),char(109),char(95),char(97),char(100),char(100),char(105),char(116),char(105),char(111),char(110),char(97),char(108),char(76),char(105),char(110),char(101),char(97),
+char(114),char(68),char(97),char(109),char(112),char(105),char(110),char(103),char(84),char(104),char(114),char(101),char(115),char(104),char(111),char(108),char(100),char(83),char(113),char(114),
+char(0),char(109),char(95),char(97),char(100),char(100),char(105),char(116),char(105),char(111),char(110),char(97),char(108),char(65),char(110),char(103),char(117),char(108),char(97),char(114),
+char(68),char(97),char(109),char(112),char(105),char(110),char(103),char(84),char(104),char(114),char(101),char(115),char(104),char(111),char(108),char(100),char(83),char(113),char(114),char(0),
+char(109),char(95),char(97),char(100),char(100),char(105),char(116),char(105),char(111),char(110),char(97),char(108),char(65),char(110),char(103),char(117),char(108),char(97),char(114),char(68),
+char(97),char(109),char(112),char(105),char(110),char(103),char(70),char(97),char(99),char(116),char(111),char(114),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),
+char(114),char(83),char(108),char(101),char(101),char(112),char(105),char(110),char(103),char(84),char(104),char(114),char(101),char(115),char(104),char(111),char(108),char(100),char(0),char(109),
+char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(83),char(108),char(101),char(101),char(112),char(105),char(110),char(103),char(84),char(104),char(114),char(101),
+char(115),char(104),char(111),char(108),char(100),char(0),char(109),char(95),char(97),char(100),char(100),char(105),char(116),char(105),char(111),char(110),char(97),char(108),char(68),char(97),
+char(109),char(112),char(105),char(110),char(103),char(0),char(109),char(95),char(110),char(117),char(109),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),
+char(116),char(82),char(111),char(119),char(115),char(0),char(110),char(117),char(98),char(0),char(42),char(109),char(95),char(114),char(98),char(65),char(0),char(42),char(109),char(95),
+char(114),char(98),char(66),char(0),char(109),char(95),char(117),char(115),char(101),char(114),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),
+char(84),char(121),char(112),char(101),char(0),char(109),char(95),char(117),char(115),char(101),char(114),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),
+char(116),char(73),char(100),char(0),char(109),char(95),char(110),char(101),char(101),char(100),char(115),char(70),char(101),char(101),char(100),char(98),char(97),char(99),char(107),char(0),
+char(109),char(95),char(97),char(112),char(112),char(108),char(105),char(101),char(100),char(73),char(109),char(112),char(117),char(108),char(115),char(101),char(0),char(109),char(95),char(100),
+char(98),char(103),char(68),char(114),char(97),char(119),char(83),char(105),char(122),char(101),char(0),char(109),char(95),char(100),char(105),char(115),char(97),char(98),char(108),char(101),
+char(67),char(111),char(108),char(108),char(105),char(115),char(105),char(111),char(110),char(115),char(66),char(101),char(116),char(119),char(101),char(101),char(110),char(76),char(105),char(110),
+char(107),char(101),char(100),char(66),char(111),char(100),char(105),char(101),char(115),char(0),char(109),char(95),char(111),char(118),char(101),char(114),char(114),char(105),char(100),char(101),
+char(78),char(117),char(109),char(83),char(111),char(108),char(118),char(101),char(114),char(73),char(116),char(101),char(114),char(97),char(116),char(105),char(111),char(110),char(115),char(0),
+char(109),char(95),char(98),char(114),char(101),char(97),char(107),char(105),char(110),char(103),char(73),char(109),char(112),char(117),char(108),char(115),char(101),char(84),char(104),char(114),
+char(101),char(115),char(104),char(111),char(108),char(100),char(0),char(109),char(95),char(105),char(115),char(69),char(110),char(97),char(98),char(108),char(101),char(100),char(0),char(112),
+char(97),char(100),char(100),char(105),char(110),char(103),char(91),char(52),char(93),char(0),char(109),char(95),char(116),char(121),char(112),char(101),char(67),char(111),char(110),char(115),
+char(116),char(114),char(97),char(105),char(110),char(116),char(68),char(97),char(116),char(97),char(0),char(109),char(95),char(112),char(105),char(118),char(111),char(116),char(73),char(110),
+char(65),char(0),char(109),char(95),char(112),char(105),char(118),char(111),char(116),char(73),char(110),char(66),char(0),char(109),char(95),char(114),char(98),char(65),char(70),char(114),
+char(97),char(109),char(101),char(0),char(109),char(95),char(114),char(98),char(66),char(70),char(114),char(97),char(109),char(101),char(0),char(109),char(95),char(117),char(115),char(101),
+char(82),char(101),char(102),char(101),char(114),char(101),char(110),char(99),char(101),char(70),char(114),char(97),char(109),char(101),char(65),char(0),char(109),char(95),char(97),char(110),
+char(103),char(117),char(108),char(97),char(114),char(79),char(110),char(108),char(121),char(0),char(109),char(95),char(101),char(110),char(97),char(98),char(108),char(101),char(65),char(110),
+char(103),char(117),char(108),char(97),char(114),char(77),char(111),char(116),char(111),char(114),char(0),char(109),char(95),char(109),char(111),char(116),char(111),char(114),char(84),char(97),
+char(114),char(103),char(101),char(116),char(86),char(101),char(108),char(111),char(99),char(105),char(116),char(121),char(0),char(109),char(95),char(109),char(97),char(120),char(77),char(111),
+char(116),char(111),char(114),char(73),char(109),char(112),char(117),char(108),char(115),char(101),char(0),char(109),char(95),char(108),char(111),char(119),char(101),char(114),char(76),char(105),
+char(109),char(105),char(116),char(0),char(109),char(95),char(117),char(112),char(112),char(101),char(114),char(76),char(105),char(109),char(105),char(116),char(0),char(109),char(95),char(108),
+char(105),char(109),char(105),char(116),char(83),char(111),char(102),char(116),char(110),char(101),char(115),char(115),char(0),char(109),char(95),char(98),char(105),char(97),char(115),char(70),
+char(97),char(99),char(116),char(111),char(114),char(0),char(109),char(95),char(114),char(101),char(108),char(97),char(120),char(97),char(116),char(105),char(111),char(110),char(70),char(97),
+char(99),char(116),char(111),char(114),char(0),char(109),char(95),char(112),char(97),char(100),char(100),char(105),char(110),char(103),char(49),char(91),char(52),char(93),char(0),char(109),
+char(95),char(115),char(119),char(105),char(110),char(103),char(83),char(112),char(97),char(110),char(49),char(0),char(109),char(95),char(115),char(119),char(105),char(110),char(103),char(83),
+char(112),char(97),char(110),char(50),char(0),char(109),char(95),char(116),char(119),char(105),char(115),char(116),char(83),char(112),char(97),char(110),char(0),char(109),char(95),char(108),
+char(105),char(110),char(101),char(97),char(114),char(85),char(112),char(112),char(101),char(114),char(76),char(105),char(109),char(105),char(116),char(0),char(109),char(95),char(108),char(105),
+char(110),char(101),char(97),char(114),char(76),char(111),char(119),char(101),char(114),char(76),char(105),char(109),char(105),char(116),char(0),char(109),char(95),char(97),char(110),char(103),
+char(117),char(108),char(97),char(114),char(85),char(112),char(112),char(101),char(114),char(76),char(105),char(109),char(105),char(116),char(0),char(109),char(95),char(97),char(110),char(103),
+char(117),char(108),char(97),char(114),char(76),char(111),char(119),char(101),char(114),char(76),char(105),char(109),char(105),char(116),char(0),char(109),char(95),char(117),char(115),char(101),
+char(76),char(105),char(110),char(101),char(97),char(114),char(82),char(101),char(102),char(101),char(114),char(101),char(110),char(99),char(101),char(70),char(114),char(97),char(109),char(101),
+char(65),char(0),char(109),char(95),char(117),char(115),char(101),char(79),char(102),char(102),char(115),char(101),char(116),char(70),char(111),char(114),char(67),char(111),char(110),char(115),
+char(116),char(114),char(97),char(105),char(110),char(116),char(70),char(114),char(97),char(109),char(101),char(0),char(109),char(95),char(54),char(100),char(111),char(102),char(68),char(97),
+char(116),char(97),char(0),char(109),char(95),char(115),char(112),char(114),char(105),char(110),char(103),char(69),char(110),char(97),char(98),char(108),char(101),char(100),char(91),char(54),
+char(93),char(0),char(109),char(95),char(101),char(113),char(117),char(105),char(108),char(105),char(98),char(114),char(105),char(117),char(109),char(80),char(111),char(105),char(110),char(116),
+char(91),char(54),char(93),char(0),char(109),char(95),char(115),char(112),char(114),char(105),char(110),char(103),char(83),char(116),char(105),char(102),char(102),char(110),char(101),char(115),
+char(115),char(91),char(54),char(93),char(0),char(109),char(95),char(115),char(112),char(114),char(105),char(110),char(103),char(68),char(97),char(109),char(112),char(105),char(110),char(103),
+char(91),char(54),char(93),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(66),char(111),char(117),char(110),char(99),char(101),char(0),char(109),
+char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(83),char(116),char(111),char(112),char(69),char(82),char(80),char(0),char(109),char(95),char(108),char(105),char(110),
+char(101),char(97),char(114),char(83),char(116),char(111),char(112),char(67),char(70),char(77),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(77),
+char(111),char(116),char(111),char(114),char(69),char(82),char(80),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(77),char(111),char(116),char(111),
+char(114),char(67),char(70),char(77),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(84),char(97),char(114),char(103),char(101),char(116),char(86),
+char(101),char(108),char(111),char(99),char(105),char(116),char(121),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(77),char(97),char(120),char(77),
+char(111),char(116),char(111),char(114),char(70),char(111),char(114),char(99),char(101),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(83),char(101),
+char(114),char(118),char(111),char(84),char(97),char(114),char(103),char(101),char(116),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(83),char(112),
+char(114),char(105),char(110),char(103),char(83),char(116),char(105),char(102),char(102),char(110),char(101),char(115),char(115),char(0),char(109),char(95),char(108),char(105),char(110),char(101),
+char(97),char(114),char(83),char(112),char(114),char(105),char(110),char(103),char(68),char(97),char(109),char(112),char(105),char(110),char(103),char(0),char(109),char(95),char(108),char(105),
+char(110),char(101),char(97),char(114),char(69),char(113),char(117),char(105),char(108),char(105),char(98),char(114),char(105),char(117),char(109),char(80),char(111),char(105),char(110),char(116),
+char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(69),char(110),char(97),char(98),char(108),char(101),char(77),char(111),char(116),char(111),char(114),
+char(91),char(52),char(93),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(83),char(101),char(114),char(118),char(111),char(77),char(111),char(116),
+char(111),char(114),char(91),char(52),char(93),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(69),char(110),char(97),char(98),char(108),char(101),
+char(83),char(112),char(114),char(105),char(110),char(103),char(91),char(52),char(93),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(83),char(112),
+char(114),char(105),char(110),char(103),char(83),char(116),char(105),char(102),char(102),char(110),char(101),char(115),char(115),char(76),char(105),char(109),char(105),char(116),char(101),char(100),
+char(91),char(52),char(93),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(83),char(112),char(114),char(105),char(110),char(103),char(68),char(97),
+char(109),char(112),char(105),char(110),char(103),char(76),char(105),char(109),char(105),char(116),char(101),char(100),char(91),char(52),char(93),char(0),char(109),char(95),char(97),char(110),
+char(103),char(117),char(108),char(97),char(114),char(66),char(111),char(117),char(110),char(99),char(101),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),
+char(114),char(83),char(116),char(111),char(112),char(69),char(82),char(80),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(83),char(116),
+char(111),char(112),char(67),char(70),char(77),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(77),char(111),char(116),char(111),char(114),
+char(69),char(82),char(80),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(77),char(111),char(116),char(111),char(114),char(67),char(70),
+char(77),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(84),char(97),char(114),char(103),char(101),char(116),char(86),char(101),char(108),
+char(111),char(99),char(105),char(116),char(121),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(77),char(97),char(120),char(77),char(111),
+char(116),char(111),char(114),char(70),char(111),char(114),char(99),char(101),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(83),char(101),
+char(114),char(118),char(111),char(84),char(97),char(114),char(103),char(101),char(116),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(83),
+char(112),char(114),char(105),char(110),char(103),char(83),char(116),char(105),char(102),char(102),char(110),char(101),char(115),char(115),char(0),char(109),char(95),char(97),char(110),char(103),
+char(117),char(108),char(97),char(114),char(83),char(112),char(114),char(105),char(110),char(103),char(68),char(97),char(109),char(112),char(105),char(110),char(103),char(0),char(109),char(95),
+char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(69),char(113),char(117),char(105),char(108),char(105),char(98),char(114),char(105),char(117),char(109),char(80),char(111),
+char(105),char(110),char(116),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(69),char(110),char(97),char(98),char(108),char(101),char(77),
+char(111),char(116),char(111),char(114),char(91),char(52),char(93),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(83),char(101),char(114),
+char(118),char(111),char(77),char(111),char(116),char(111),char(114),char(91),char(52),char(93),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),
+char(69),char(110),char(97),char(98),char(108),char(101),char(83),char(112),char(114),char(105),char(110),char(103),char(91),char(52),char(93),char(0),char(109),char(95),char(97),char(110),
+char(103),char(117),char(108),char(97),char(114),char(83),char(112),char(114),char(105),char(110),char(103),char(83),char(116),char(105),char(102),char(102),char(110),char(101),char(115),char(115),
+char(76),char(105),char(109),char(105),char(116),char(101),char(100),char(91),char(52),char(93),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),
+char(83),char(112),char(114),char(105),char(110),char(103),char(68),char(97),char(109),char(112),char(105),char(110),char(103),char(76),char(105),char(109),char(105),char(116),char(101),char(100),
+char(91),char(52),char(93),char(0),char(109),char(95),char(114),char(111),char(116),char(97),char(116),char(101),char(79),char(114),char(100),char(101),char(114),char(0),char(109),char(95),
+char(97),char(120),char(105),char(115),char(73),char(110),char(65),char(0),char(109),char(95),char(97),char(120),char(105),char(115),char(73),char(110),char(66),char(0),char(109),char(95),
+char(114),char(97),char(116),char(105),char(111),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(83),char(116),char(105),char(102),char(102),char(110),
+char(101),char(115),char(115),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(83),char(116),char(105),char(102),char(102),char(110),char(101),
+char(115),char(115),char(0),char(109),char(95),char(118),char(111),char(108),char(117),char(109),char(101),char(83),char(116),char(105),char(102),char(102),char(110),char(101),char(115),char(115),
+char(0),char(42),char(109),char(95),char(109),char(97),char(116),char(101),char(114),char(105),char(97),char(108),char(0),char(109),char(95),char(112),char(111),char(115),char(105),char(116),
+char(105),char(111),char(110),char(0),char(109),char(95),char(112),char(114),char(101),char(118),char(105),char(111),char(117),char(115),char(80),char(111),char(115),char(105),char(116),char(105),
+char(111),char(110),char(0),char(109),char(95),char(118),char(101),char(108),char(111),char(99),char(105),char(116),char(121),char(0),char(109),char(95),char(97),char(99),char(99),char(117),
+char(109),char(117),char(108),char(97),char(116),char(101),char(100),char(70),char(111),char(114),char(99),char(101),char(0),char(109),char(95),char(110),char(111),char(114),char(109),char(97),
+char(108),char(0),char(109),char(95),char(97),char(114),char(101),char(97),char(0),char(109),char(95),char(97),char(116),char(116),char(97),char(99),char(104),char(0),char(109),char(95),
+char(110),char(111),char(100),char(101),char(73),char(110),char(100),char(105),char(99),char(101),char(115),char(91),char(50),char(93),char(0),char(109),char(95),char(114),char(101),char(115),
+char(116),char(76),char(101),char(110),char(103),char(116),char(104),char(0),char(109),char(95),char(98),char(98),char(101),char(110),char(100),char(105),char(110),char(103),char(0),char(109),
+char(95),char(110),char(111),char(100),char(101),char(73),char(110),char(100),char(105),char(99),char(101),char(115),char(91),char(51),char(93),char(0),char(109),char(95),char(114),char(101),
+char(115),char(116),char(65),char(114),char(101),char(97),char(0),char(109),char(95),char(99),char(48),char(91),char(52),char(93),char(0),char(109),char(95),char(110),char(111),char(100),
+char(101),char(73),char(110),char(100),char(105),char(99),char(101),char(115),char(91),char(52),char(93),char(0),char(109),char(95),char(114),char(101),char(115),char(116),char(86),char(111),
+char(108),char(117),char(109),char(101),char(0),char(109),char(95),char(99),char(49),char(0),char(109),char(95),char(99),char(50),char(0),char(109),char(95),char(99),char(48),char(0),
+char(109),char(95),char(108),char(111),char(99),char(97),char(108),char(70),char(114),char(97),char(109),char(101),char(0),char(42),char(109),char(95),char(114),char(105),char(103),char(105),
+char(100),char(66),char(111),char(100),char(121),char(0),char(109),char(95),char(110),char(111),char(100),char(101),char(73),char(110),char(100),char(101),char(120),char(0),char(109),char(95),
+char(97),char(101),char(114),char(111),char(77),char(111),char(100),char(101),char(108),char(0),char(109),char(95),char(98),char(97),char(117),char(109),char(103),char(97),char(114),char(116),
+char(101),char(0),char(109),char(95),char(100),char(114),char(97),char(103),char(0),char(109),char(95),char(108),char(105),char(102),char(116),char(0),char(109),char(95),char(112),char(114),
+char(101),char(115),char(115),char(117),char(114),char(101),char(0),char(109),char(95),char(118),char(111),char(108),char(117),char(109),char(101),char(0),char(109),char(95),char(100),char(121),
+char(110),char(97),char(109),char(105),char(99),char(70),char(114),char(105),char(99),char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(112),char(111),char(115),char(101),
+char(77),char(97),char(116),char(99),char(104),char(0),char(109),char(95),char(114),char(105),char(103),char(105),char(100),char(67),char(111),char(110),char(116),char(97),char(99),char(116),
+char(72),char(97),char(114),char(100),char(110),char(101),char(115),char(115),char(0),char(109),char(95),char(107),char(105),char(110),char(101),char(116),char(105),char(99),char(67),char(111),
+char(110),char(116),char(97),char(99),char(116),char(72),char(97),char(114),char(100),char(110),char(101),char(115),char(115),char(0),char(109),char(95),char(115),char(111),char(102),char(116),
+char(67),char(111),char(110),char(116),char(97),char(99),char(116),char(72),char(97),char(114),char(100),char(110),char(101),char(115),char(115),char(0),char(109),char(95),char(97),char(110),
+char(99),char(104),char(111),char(114),char(72),char(97),char(114),char(100),char(110),char(101),char(115),char(115),char(0),char(109),char(95),char(115),char(111),char(102),char(116),char(82),
+char(105),char(103),char(105),char(100),char(67),char(108),char(117),char(115),char(116),char(101),char(114),char(72),char(97),char(114),char(100),char(110),char(101),char(115),char(115),char(0),
+char(109),char(95),char(115),char(111),char(102),char(116),char(75),char(105),char(110),char(101),char(116),char(105),char(99),char(67),char(108),char(117),char(115),char(116),char(101),char(114),
+char(72),char(97),char(114),char(100),char(110),char(101),char(115),char(115),char(0),char(109),char(95),char(115),char(111),char(102),char(116),char(83),char(111),char(102),char(116),char(67),
+char(108),char(117),char(115),char(116),char(101),char(114),char(72),char(97),char(114),char(100),char(110),char(101),char(115),char(115),char(0),char(109),char(95),char(115),char(111),char(102),
+char(116),char(82),char(105),char(103),char(105),char(100),char(67),char(108),char(117),char(115),char(116),char(101),char(114),char(73),char(109),char(112),char(117),char(108),char(115),char(101),
+char(83),char(112),char(108),char(105),char(116),char(0),char(109),char(95),char(115),char(111),char(102),char(116),char(75),char(105),char(110),char(101),char(116),char(105),char(99),char(67),
+char(108),char(117),char(115),char(116),char(101),char(114),char(73),char(109),char(112),char(117),char(108),char(115),char(101),char(83),char(112),char(108),char(105),char(116),char(0),char(109),
+char(95),char(115),char(111),char(102),char(116),char(83),char(111),char(102),char(116),char(67),char(108),char(117),char(115),char(116),char(101),char(114),char(73),char(109),char(112),char(117),
+char(108),char(115),char(101),char(83),char(112),char(108),char(105),char(116),char(0),char(109),char(95),char(109),char(97),char(120),char(86),char(111),char(108),char(117),char(109),char(101),
+char(0),char(109),char(95),char(116),char(105),char(109),char(101),char(83),char(99),char(97),char(108),char(101),char(0),char(109),char(95),char(118),char(101),char(108),char(111),char(99),
+char(105),char(116),char(121),char(73),char(116),char(101),char(114),char(97),char(116),char(105),char(111),char(110),char(115),char(0),char(109),char(95),char(112),char(111),char(115),char(105),
+char(116),char(105),char(111),char(110),char(73),char(116),char(101),char(114),char(97),char(116),char(105),char(111),char(110),char(115),char(0),char(109),char(95),char(100),char(114),char(105),
+char(102),char(116),char(73),char(116),char(101),char(114),char(97),char(116),char(105),char(111),char(110),char(115),char(0),char(109),char(95),char(99),char(108),char(117),char(115),char(116),
+char(101),char(114),char(73),char(116),char(101),char(114),char(97),char(116),char(105),char(111),char(110),char(115),char(0),char(109),char(95),char(114),char(111),char(116),char(0),char(109),
+char(95),char(115),char(99),char(97),char(108),char(101),char(0),char(109),char(95),char(97),char(113),char(113),char(0),char(109),char(95),char(99),char(111),char(109),char(0),char(42),
+char(109),char(95),char(112),char(111),char(115),char(105),char(116),char(105),char(111),char(110),char(115),char(0),char(42),char(109),char(95),char(119),char(101),char(105),char(103),char(104),
+char(116),char(115),char(0),char(109),char(95),char(110),char(117),char(109),char(80),char(111),char(115),char(105),char(116),char(105),char(111),char(110),char(115),char(0),char(109),char(95),
+char(110),char(117),char(109),char(87),char(101),char(105),char(103),char(116),char(115),char(0),char(109),char(95),char(98),char(118),char(111),char(108),char(117),char(109),char(101),char(0),
+char(109),char(95),char(98),char(102),char(114),char(97),char(109),char(101),char(0),char(109),char(95),char(102),char(114),char(97),char(109),char(101),char(120),char(102),char(111),char(114),
+char(109),char(0),char(109),char(95),char(108),char(111),char(99),char(105),char(105),char(0),char(109),char(95),char(105),char(110),char(118),char(119),char(105),char(0),char(109),char(95),
+char(118),char(105),char(109),char(112),char(117),char(108),char(115),char(101),char(115),char(91),char(50),char(93),char(0),char(109),char(95),char(100),char(105),char(109),char(112),char(117),
+char(108),char(115),char(101),char(115),char(91),char(50),char(93),char(0),char(109),char(95),char(108),char(118),char(0),char(109),char(95),char(97),char(118),char(0),char(42),char(109),
+char(95),char(102),char(114),char(97),char(109),char(101),char(114),char(101),char(102),char(115),char(0),char(42),char(109),char(95),char(110),char(111),char(100),char(101),char(73),char(110),
+char(100),char(105),char(99),char(101),char(115),char(0),char(42),char(109),char(95),char(109),char(97),char(115),char(115),char(101),char(115),char(0),char(109),char(95),char(110),char(117),
+char(109),char(70),char(114),char(97),char(109),char(101),char(82),char(101),char(102),char(115),char(0),char(109),char(95),char(110),char(117),char(109),char(78),char(111),char(100),char(101),
+char(115),char(0),char(109),char(95),char(110),char(117),char(109),char(77),char(97),char(115),char(115),char(101),char(115),char(0),char(109),char(95),char(105),char(100),char(109),char(97),
+char(115),char(115),char(0),char(109),char(95),char(105),char(109),char(97),char(115),char(115),char(0),char(109),char(95),char(110),char(118),char(105),char(109),char(112),char(117),char(108),
+char(115),char(101),char(115),char(0),char(109),char(95),char(110),char(100),char(105),char(109),char(112),char(117),char(108),char(115),char(101),char(115),char(0),char(109),char(95),char(110),
+char(100),char(97),char(109),char(112),char(105),char(110),char(103),char(0),char(109),char(95),char(108),char(100),char(97),char(109),char(112),char(105),char(110),char(103),char(0),char(109),
+char(95),char(97),char(100),char(97),char(109),char(112),char(105),char(110),char(103),char(0),char(109),char(95),char(109),char(97),char(116),char(99),char(104),char(105),char(110),char(103),
+char(0),char(109),char(95),char(109),char(97),char(120),char(83),char(101),char(108),char(102),char(67),char(111),char(108),char(108),char(105),char(115),char(105),char(111),char(110),char(73),
+char(109),char(112),char(117),char(108),char(115),char(101),char(0),char(109),char(95),char(115),char(101),char(108),char(102),char(67),char(111),char(108),char(108),char(105),char(115),char(105),
+char(111),char(110),char(73),char(109),char(112),char(117),char(108),char(115),char(101),char(70),char(97),char(99),char(116),char(111),char(114),char(0),char(109),char(95),char(99),char(111),
+char(110),char(116),char(97),char(105),char(110),char(115),char(65),char(110),char(99),char(104),char(111),char(114),char(0),char(109),char(95),char(99),char(111),char(108),char(108),char(105),
+char(100),char(101),char(0),char(109),char(95),char(99),char(108),char(117),char(115),char(116),char(101),char(114),char(73),char(110),char(100),char(101),char(120),char(0),char(42),char(109),
+char(95),char(98),char(111),char(100),char(121),char(65),char(0),char(42),char(109),char(95),char(98),char(111),char(100),char(121),char(66),char(0),char(109),char(95),char(114),char(101),
+char(102),char(115),char(91),char(50),char(93),char(0),char(109),char(95),char(99),char(102),char(109),char(0),char(109),char(95),char(115),char(112),char(108),char(105),char(116),char(0),
+char(109),char(95),char(100),char(101),char(108),char(101),char(116),char(101),char(0),char(109),char(95),char(114),char(101),char(108),char(80),char(111),char(115),char(105),char(116),char(105),
+char(111),char(110),char(91),char(50),char(93),char(0),char(109),char(95),char(98),char(111),char(100),char(121),char(65),char(116),char(121),char(112),char(101),char(0),char(109),char(95),
+char(98),char(111),char(100),char(121),char(66),char(116),char(121),char(112),char(101),char(0),char(109),char(95),char(106),char(111),char(105),char(110),char(116),char(84),char(121),char(112),
+char(101),char(0),char(42),char(109),char(95),char(112),char(111),char(115),char(101),char(0),char(42),char(42),char(109),char(95),char(109),char(97),char(116),char(101),char(114),char(105),
+char(97),char(108),char(115),char(0),char(42),char(109),char(95),char(110),char(111),char(100),char(101),char(115),char(0),char(42),char(109),char(95),char(108),char(105),char(110),char(107),
+char(115),char(0),char(42),char(109),char(95),char(102),char(97),char(99),char(101),char(115),char(0),char(42),char(109),char(95),char(116),char(101),char(116),char(114),char(97),char(104),
+char(101),char(100),char(114),char(97),char(0),char(42),char(109),char(95),char(97),char(110),char(99),char(104),char(111),char(114),char(115),char(0),char(42),char(109),char(95),char(99),
+char(108),char(117),char(115),char(116),char(101),char(114),char(115),char(0),char(42),char(109),char(95),char(106),char(111),char(105),char(110),char(116),char(115),char(0),char(109),char(95),
+char(110),char(117),char(109),char(77),char(97),char(116),char(101),char(114),char(105),char(97),char(108),char(115),char(0),char(109),char(95),char(110),char(117),char(109),char(76),char(105),
+char(110),char(107),char(115),char(0),char(109),char(95),char(110),char(117),char(109),char(70),char(97),char(99),char(101),char(115),char(0),char(109),char(95),char(110),char(117),char(109),
+char(84),char(101),char(116),char(114),char(97),char(104),char(101),char(100),char(114),char(97),char(0),char(109),char(95),char(110),char(117),char(109),char(65),char(110),char(99),char(104),
+char(111),char(114),char(115),char(0),char(109),char(95),char(110),char(117),char(109),char(67),char(108),char(117),char(115),char(116),char(101),char(114),char(115),char(0),char(109),char(95),
+char(110),char(117),char(109),char(74),char(111),char(105),char(110),char(116),char(115),char(0),char(109),char(95),char(99),char(111),char(110),char(102),char(105),char(103),char(0),char(109),
+char(95),char(122),char(101),char(114),char(111),char(82),char(111),char(116),char(80),char(97),char(114),char(101),char(110),char(116),char(84),char(111),char(84),char(104),char(105),char(115),
+char(0),char(109),char(95),char(112),char(97),char(114),char(101),char(110),char(116),char(67),char(111),char(109),char(84),char(111),char(84),char(104),char(105),char(115),char(80),char(105),
+char(118),char(111),char(116),char(79),char(102),char(102),char(115),char(101),char(116),char(0),char(109),char(95),char(116),char(104),char(105),char(115),char(80),char(105),char(118),char(111),
+char(116),char(84),char(111),char(84),char(104),char(105),char(115),char(67),char(111),char(109),char(79),char(102),char(102),char(115),char(101),char(116),char(0),char(109),char(95),char(106),
+char(111),char(105),char(110),char(116),char(65),char(120),char(105),char(115),char(84),char(111),char(112),char(91),char(54),char(93),char(0),char(109),char(95),char(106),char(111),char(105),
+char(110),char(116),char(65),char(120),char(105),char(115),char(66),char(111),char(116),char(116),char(111),char(109),char(91),char(54),char(93),char(0),char(109),char(95),char(108),char(105),
+char(110),char(107),char(73),char(110),char(101),char(114),char(116),char(105),char(97),char(0),char(109),char(95),char(97),char(98),char(115),char(70),char(114),char(97),char(109),char(101),
+char(84),char(111),char(116),char(86),char(101),char(108),char(111),char(99),char(105),char(116),char(121),char(84),char(111),char(112),char(0),char(109),char(95),char(97),char(98),char(115),
+char(70),char(114),char(97),char(109),char(101),char(84),char(111),char(116),char(86),char(101),char(108),char(111),char(99),char(105),char(116),char(121),char(66),char(111),char(116),char(116),
+char(111),char(109),char(0),char(109),char(95),char(97),char(98),char(115),char(70),char(114),char(97),char(109),char(101),char(76),char(111),char(99),char(86),char(101),char(108),char(111),
+char(99),char(105),char(116),char(121),char(84),char(111),char(112),char(0),char(109),char(95),char(97),char(98),char(115),char(70),char(114),char(97),char(109),char(101),char(76),char(111),
+char(99),char(86),char(101),char(108),char(111),char(99),char(105),char(116),char(121),char(66),char(111),char(116),char(116),char(111),char(109),char(0),char(109),char(95),char(108),char(105),
+char(110),char(107),char(77),char(97),char(115),char(115),char(0),char(109),char(95),char(112),char(97),char(114),char(101),char(110),char(116),char(73),char(110),char(100),char(101),char(120),
+char(0),char(109),char(95),char(100),char(111),char(102),char(67),char(111),char(117),char(110),char(116),char(0),char(109),char(95),char(112),char(111),char(115),char(86),char(97),char(114),
+char(67),char(111),char(117),char(110),char(116),char(0),char(109),char(95),char(106),char(111),char(105),char(110),char(116),char(80),char(111),char(115),char(91),char(55),char(93),char(0),
+char(109),char(95),char(106),char(111),char(105),char(110),char(116),char(86),char(101),char(108),char(91),char(54),char(93),char(0),char(109),char(95),char(106),char(111),char(105),char(110),
+char(116),char(84),char(111),char(114),char(113),char(117),char(101),char(91),char(54),char(93),char(0),char(109),char(95),char(106),char(111),char(105),char(110),char(116),char(68),char(97),
+char(109),char(112),char(105),char(110),char(103),char(0),char(109),char(95),char(106),char(111),char(105),char(110),char(116),char(70),char(114),char(105),char(99),char(116),char(105),char(111),
+char(110),char(0),char(109),char(95),char(106),char(111),char(105),char(110),char(116),char(76),char(111),char(119),char(101),char(114),char(76),char(105),char(109),char(105),char(116),char(0),
+char(109),char(95),char(106),char(111),char(105),char(110),char(116),char(85),char(112),char(112),char(101),char(114),char(76),char(105),char(109),char(105),char(116),char(0),char(109),char(95),
+char(106),char(111),char(105),char(110),char(116),char(77),char(97),char(120),char(70),char(111),char(114),char(99),char(101),char(0),char(109),char(95),char(106),char(111),char(105),char(110),
+char(116),char(77),char(97),char(120),char(86),char(101),char(108),char(111),char(99),char(105),char(116),char(121),char(0),char(42),char(109),char(95),char(108),char(105),char(110),char(107),
+char(78),char(97),char(109),char(101),char(0),char(42),char(109),char(95),char(106),char(111),char(105),char(110),char(116),char(78),char(97),char(109),char(101),char(0),char(42),char(109),
+char(95),char(108),char(105),char(110),char(107),char(67),char(111),char(108),char(108),char(105),char(100),char(101),char(114),char(0),char(42),char(109),char(95),char(112),char(97),char(100),
+char(100),char(105),char(110),char(103),char(80),char(116),char(114),char(0),char(109),char(95),char(98),char(97),char(115),char(101),char(87),char(111),char(114),char(108),char(100),char(80),
+char(111),char(115),char(105),char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(98),char(97),char(115),char(101),char(87),char(111),char(114),char(108),char(100),char(79),
+char(114),char(105),char(101),char(110),char(116),char(97),char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(98),char(97),char(115),char(101),char(76),char(105),char(110),
+char(101),char(97),char(114),char(86),char(101),char(108),char(111),char(99),char(105),char(116),char(121),char(0),char(109),char(95),char(98),char(97),char(115),char(101),char(65),char(110),
+char(103),char(117),char(108),char(97),char(114),char(86),char(101),char(108),char(111),char(99),char(105),char(116),char(121),char(0),char(109),char(95),char(98),char(97),char(115),char(101),
+char(73),char(110),char(101),char(114),char(116),char(105),char(97),char(0),char(109),char(95),char(98),char(97),char(115),char(101),char(77),char(97),char(115),char(115),char(0),char(42),
+char(109),char(95),char(98),char(97),char(115),char(101),char(78),char(97),char(109),char(101),char(0),char(42),char(109),char(95),char(98),char(97),char(115),char(101),char(67),char(111),
+char(108),char(108),char(105),char(100),char(101),char(114),char(0),char(109),char(95),char(99),char(111),char(108),char(79),char(98),char(106),char(68),char(97),char(116),char(97),char(0),
+char(42),char(109),char(95),char(109),char(117),char(108),char(116),char(105),char(66),char(111),char(100),char(121),char(0),char(109),char(95),char(108),char(105),char(110),char(107),char(0),
+char(84),char(89),char(80),char(69),char(99),char(0),char(0),char(0),char(99),char(104),char(97),char(114),char(0),char(117),char(99),char(104),char(97),char(114),char(0),char(115),
+char(104),char(111),char(114),char(116),char(0),char(117),char(115),char(104),char(111),char(114),char(116),char(0),char(105),char(110),char(116),char(0),char(108),char(111),char(110),char(103),
+char(0),char(117),char(108),char(111),char(110),char(103),char(0),char(102),char(108),char(111),char(97),char(116),char(0),char(100),char(111),char(117),char(98),char(108),char(101),char(0),
+char(118),char(111),char(105),char(100),char(0),char(80),char(111),char(105),char(110),char(116),char(101),char(114),char(65),char(114),char(114),char(97),char(121),char(0),char(98),char(116),
+char(80),char(104),char(121),char(115),char(105),char(99),char(115),char(83),char(121),char(115),char(116),char(101),char(109),char(0),char(76),char(105),char(115),char(116),char(66),char(97),
+char(115),char(101),char(0),char(98),char(116),char(86),char(101),char(99),char(116),char(111),char(114),char(51),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),
+char(97),char(0),char(98),char(116),char(86),char(101),char(99),char(116),char(111),char(114),char(51),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),
+char(97),char(0),char(98),char(116),char(81),char(117),char(97),char(116),char(101),char(114),char(110),char(105),char(111),char(110),char(70),char(108),char(111),char(97),char(116),char(68),
+char(97),char(116),char(97),char(0),char(98),char(116),char(81),char(117),char(97),char(116),char(101),char(114),char(110),char(105),char(111),char(110),char(68),char(111),char(117),char(98),
+char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(77),char(97),char(116),char(114),char(105),char(120),char(51),char(120),char(51),char(70),char(108),
+char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(77),char(97),char(116),char(114),char(105),char(120),char(51),char(120),char(51),char(68),
+char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(84),char(114),char(97),char(110),char(115),char(102),char(111),char(114),
+char(109),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(84),char(114),char(97),char(110),char(115),char(102),char(111),
+char(114),char(109),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(66),char(118),char(104),char(83),char(117),
+char(98),char(116),char(114),char(101),char(101),char(73),char(110),char(102),char(111),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(79),char(112),char(116),char(105),
+char(109),char(105),char(122),char(101),char(100),char(66),char(118),char(104),char(78),char(111),char(100),char(101),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),
char(97),char(0),char(98),char(116),char(79),char(112),char(116),char(105),char(109),char(105),char(122),char(101),char(100),char(66),char(118),char(104),char(78),char(111),char(100),char(101),
-char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(79),char(112),char(116),char(105),char(109),char(105),char(122),char(101),
-char(100),char(66),char(118),char(104),char(78),char(111),char(100),char(101),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),
-char(116),char(81),char(117),char(97),char(110),char(116),char(105),char(122),char(101),char(100),char(66),char(118),char(104),char(78),char(111),char(100),char(101),char(68),char(97),char(116),
-char(97),char(0),char(98),char(116),char(81),char(117),char(97),char(110),char(116),char(105),char(122),char(101),char(100),char(66),char(118),char(104),char(70),char(108),char(111),char(97),
-char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(81),char(117),char(97),char(110),char(116),char(105),char(122),char(101),char(100),char(66),char(118),char(104),
-char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(111),char(108),char(108),char(105),char(115),char(105),
-char(111),char(110),char(83),char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(83),char(116),char(97),char(116),char(105),char(99),
-char(80),char(108),char(97),char(110),char(101),char(83),char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(111),char(110),
-char(118),char(101),char(120),char(73),char(110),char(116),char(101),char(114),char(110),char(97),char(108),char(83),char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97),
-char(0),char(98),char(116),char(80),char(111),char(115),char(105),char(116),char(105),char(111),char(110),char(65),char(110),char(100),char(82),char(97),char(100),char(105),char(117),char(115),
-char(0),char(98),char(116),char(77),char(117),char(108),char(116),char(105),char(83),char(112),char(104),char(101),char(114),char(101),char(83),char(104),char(97),char(112),char(101),char(68),
-char(97),char(116),char(97),char(0),char(98),char(116),char(73),char(110),char(116),char(73),char(110),char(100),char(101),char(120),char(68),char(97),char(116),char(97),char(0),char(98),
-char(116),char(83),char(104),char(111),char(114),char(116),char(73),char(110),char(116),char(73),char(110),char(100),char(101),char(120),char(68),char(97),char(116),char(97),char(0),char(98),
-char(116),char(83),char(104),char(111),char(114),char(116),char(73),char(110),char(116),char(73),char(110),char(100),char(101),char(120),char(84),char(114),char(105),char(112),char(108),char(101),
-char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(104),char(97),char(114),char(73),char(110),char(100),char(101),char(120),char(84),char(114),char(105),
-char(112),char(108),char(101),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(77),char(101),char(115),char(104),char(80),char(97),char(114),char(116),char(68),
-char(97),char(116),char(97),char(0),char(98),char(116),char(83),char(116),char(114),char(105),char(100),char(105),char(110),char(103),char(77),char(101),char(115),char(104),char(73),char(110),
-char(116),char(101),char(114),char(102),char(97),char(99),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(84),char(114),char(105),char(97),char(110),char(103),
-char(108),char(101),char(77),char(101),char(115),char(104),char(83),char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(84),char(114),
-char(105),char(97),char(110),char(103),char(108),char(101),char(73),char(110),char(102),char(111),char(77),char(97),char(112),char(68),char(97),char(116),char(97),char(0),char(98),char(116),
-char(83),char(99),char(97),char(108),char(101),char(100),char(84),char(114),char(105),char(97),char(110),char(103),char(108),char(101),char(77),char(101),char(115),char(104),char(83),char(104),
-char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(111),char(109),char(112),char(111),char(117),char(110),char(100),char(83),char(104),
-char(97),char(112),char(101),char(67),char(104),char(105),char(108),char(100),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(111),char(109),char(112),char(111),
-char(117),char(110),char(100),char(83),char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(121),char(108),char(105),char(110),
-char(100),char(101),char(114),char(83),char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(111),char(110),char(101),char(83),
-char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(97),char(112),char(115),char(117),char(108),char(101),char(83),char(104),
+char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(81),char(117),char(97),char(110),char(116),char(105),char(122),
+char(101),char(100),char(66),char(118),char(104),char(78),char(111),char(100),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(81),char(117),char(97),char(110),
+char(116),char(105),char(122),char(101),char(100),char(66),char(118),char(104),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),
+char(81),char(117),char(97),char(110),char(116),char(105),char(122),char(101),char(100),char(66),char(118),char(104),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),
+char(116),char(97),char(0),char(98),char(116),char(67),char(111),char(108),char(108),char(105),char(115),char(105),char(111),char(110),char(83),char(104),char(97),char(112),char(101),char(68),
+char(97),char(116),char(97),char(0),char(98),char(116),char(83),char(116),char(97),char(116),char(105),char(99),char(80),char(108),char(97),char(110),char(101),char(83),char(104),char(97),
+char(112),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(111),char(110),char(118),char(101),char(120),char(73),char(110),char(116),char(101),char(114),
+char(110),char(97),char(108),char(83),char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(80),char(111),char(115),char(105),char(116),
+char(105),char(111),char(110),char(65),char(110),char(100),char(82),char(97),char(100),char(105),char(117),char(115),char(0),char(98),char(116),char(77),char(117),char(108),char(116),char(105),
+char(83),char(112),char(104),char(101),char(114),char(101),char(83),char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(73),char(110),
+char(116),char(73),char(110),char(100),char(101),char(120),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(83),char(104),char(111),char(114),char(116),char(73),char(110),
+char(116),char(73),char(110),char(100),char(101),char(120),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(83),char(104),char(111),char(114),char(116),char(73),char(110),
+char(116),char(73),char(110),char(100),char(101),char(120),char(84),char(114),char(105),char(112),char(108),char(101),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),
+char(67),char(104),char(97),char(114),char(73),char(110),char(100),char(101),char(120),char(84),char(114),char(105),char(112),char(108),char(101),char(116),char(68),char(97),char(116),char(97),
+char(0),char(98),char(116),char(77),char(101),char(115),char(104),char(80),char(97),char(114),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(83),char(116),
+char(114),char(105),char(100),char(105),char(110),char(103),char(77),char(101),char(115),char(104),char(73),char(110),char(116),char(101),char(114),char(102),char(97),char(99),char(101),char(68),
+char(97),char(116),char(97),char(0),char(98),char(116),char(84),char(114),char(105),char(97),char(110),char(103),char(108),char(101),char(77),char(101),char(115),char(104),char(83),char(104),
char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(84),char(114),char(105),char(97),char(110),char(103),char(108),char(101),char(73),char(110),
-char(102),char(111),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(80),char(101),char(114),char(115),char(105),char(115),char(116),char(101),char(110),char(116),char(77),
-char(97),char(110),char(105),char(102),char(111),char(108),char(100),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),
-char(67),char(111),char(108),char(108),char(105),char(115),char(105),char(111),char(110),char(79),char(98),char(106),char(101),char(99),char(116),char(68),char(111),char(117),char(98),char(108),
-char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(80),char(101),char(114),char(115),char(105),char(115),char(116),char(101),char(110),char(116),char(77),char(97),
-char(110),char(105),char(102),char(111),char(108),char(100),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(111),
-char(108),char(108),char(105),char(115),char(105),char(111),char(110),char(79),char(98),char(106),char(101),char(99),char(116),char(70),char(108),char(111),char(97),char(116),char(68),char(97),
-char(116),char(97),char(0),char(98),char(116),char(71),char(73),char(109),char(112),char(97),char(99),char(116),char(77),char(101),char(115),char(104),char(83),char(104),char(97),char(112),
-char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(111),char(110),char(118),char(101),char(120),char(72),char(117),char(108),char(108),char(83),char(104),
-char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(111),char(110),char(116),char(97),char(99),char(116),char(83),char(111),char(108),
-char(118),char(101),char(114),char(73),char(110),char(102),char(111),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),
-char(67),char(111),char(110),char(116),char(97),char(99),char(116),char(83),char(111),char(108),char(118),char(101),char(114),char(73),char(110),char(102),char(111),char(70),char(108),char(111),
-char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(68),char(121),char(110),char(97),char(109),char(105),char(99),char(115),char(87),char(111),char(114),
-char(108),char(100),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(68),char(121),char(110),char(97),char(109),
-char(105),char(99),char(115),char(87),char(111),char(114),char(108),char(100),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),
-char(82),char(105),char(103),char(105),char(100),char(66),char(111),char(100),char(121),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),
-char(116),char(82),char(105),char(103),char(105),char(100),char(66),char(111),char(100),char(121),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),
-char(0),char(98),char(116),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(73),char(110),char(102),char(111),char(49),char(0),char(98),
-char(116),char(84),char(121),char(112),char(101),char(100),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(70),char(108),char(111),char(97),
-char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(84),char(121),char(112),char(101),char(100),char(67),char(111),char(110),char(115),char(116),char(114),char(97),
-char(105),char(110),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(82),char(105),char(103),char(105),char(100),char(66),char(111),char(100),char(121),char(68),
-char(97),char(116),char(97),char(0),char(98),char(116),char(84),char(121),char(112),char(101),char(100),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),
-char(116),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(80),char(111),char(105),char(110),char(116),char(50),
-char(80),char(111),char(105),char(110),char(116),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(70),char(108),char(111),char(97),char(116),
-char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(80),char(111),char(105),char(110),char(116),char(50),char(80),char(111),char(105),char(110),char(116),char(67),char(111),
-char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(50),char(0),
-char(98),char(116),char(80),char(111),char(105),char(110),char(116),char(50),char(80),char(111),char(105),char(110),char(116),char(67),char(111),char(110),char(115),char(116),char(114),char(97),
+char(102),char(111),char(77),char(97),char(112),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(83),char(99),char(97),char(108),char(101),char(100),char(84),char(114),
+char(105),char(97),char(110),char(103),char(108),char(101),char(77),char(101),char(115),char(104),char(83),char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),
+char(98),char(116),char(67),char(111),char(109),char(112),char(111),char(117),char(110),char(100),char(83),char(104),char(97),char(112),char(101),char(67),char(104),char(105),char(108),char(100),
+char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(111),char(109),char(112),char(111),char(117),char(110),char(100),char(83),char(104),char(97),char(112),char(101),
+char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(121),char(108),char(105),char(110),char(100),char(101),char(114),char(83),char(104),char(97),char(112),char(101),
+char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(111),char(110),char(101),char(83),char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97),
+char(0),char(98),char(116),char(67),char(97),char(112),char(115),char(117),char(108),char(101),char(83),char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),
+char(98),char(116),char(84),char(114),char(105),char(97),char(110),char(103),char(108),char(101),char(73),char(110),char(102),char(111),char(68),char(97),char(116),char(97),char(0),char(98),
+char(116),char(80),char(101),char(114),char(115),char(105),char(115),char(116),char(101),char(110),char(116),char(77),char(97),char(110),char(105),char(102),char(111),char(108),char(100),char(68),
+char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(111),char(108),char(108),char(105),char(115),char(105),char(111),
+char(110),char(79),char(98),char(106),char(101),char(99),char(116),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),
+char(80),char(101),char(114),char(115),char(105),char(115),char(116),char(101),char(110),char(116),char(77),char(97),char(110),char(105),char(102),char(111),char(108),char(100),char(70),char(108),
+char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(111),char(108),char(108),char(105),char(115),char(105),char(111),char(110),char(79),
+char(98),char(106),char(101),char(99),char(116),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(71),char(73),char(109),
+char(112),char(97),char(99),char(116),char(77),char(101),char(115),char(104),char(83),char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),
+char(67),char(111),char(110),char(118),char(101),char(120),char(72),char(117),char(108),char(108),char(83),char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),
+char(98),char(116),char(67),char(111),char(110),char(116),char(97),char(99),char(116),char(83),char(111),char(108),char(118),char(101),char(114),char(73),char(110),char(102),char(111),char(68),
+char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(111),char(110),char(116),char(97),char(99),char(116),char(83),
+char(111),char(108),char(118),char(101),char(114),char(73),char(110),char(102),char(111),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),
+char(116),char(68),char(121),char(110),char(97),char(109),char(105),char(99),char(115),char(87),char(111),char(114),char(108),char(100),char(68),char(111),char(117),char(98),char(108),char(101),
+char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(68),char(121),char(110),char(97),char(109),char(105),char(99),char(115),char(87),char(111),char(114),char(108),char(100),
+char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(82),char(105),char(103),char(105),char(100),char(66),char(111),char(100),
+char(121),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(82),char(105),char(103),char(105),char(100),char(66),char(111),
+char(100),char(121),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(111),char(110),char(115),char(116),
+char(114),char(97),char(105),char(110),char(116),char(73),char(110),char(102),char(111),char(49),char(0),char(98),char(116),char(84),char(121),char(112),char(101),char(100),char(67),char(111),
+char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),
+char(84),char(121),char(112),char(101),char(100),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(68),char(97),char(116),char(97),char(0),
+char(98),char(116),char(82),char(105),char(103),char(105),char(100),char(66),char(111),char(100),char(121),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(84),char(121),
+char(112),char(101),char(100),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(68),char(111),char(117),char(98),char(108),char(101),char(68),
+char(97),char(116),char(97),char(0),char(98),char(116),char(80),char(111),char(105),char(110),char(116),char(50),char(80),char(111),char(105),char(110),char(116),char(67),char(111),char(110),
+char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(80),
+char(111),char(105),char(110),char(116),char(50),char(80),char(111),char(105),char(110),char(116),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),
+char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(50),char(0),char(98),char(116),char(80),char(111),char(105),char(110),char(116),char(50),
+char(80),char(111),char(105),char(110),char(116),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(68),char(111),char(117),char(98),char(108),
+char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(72),char(105),char(110),char(103),char(101),char(67),char(111),char(110),char(115),char(116),char(114),char(97),
char(105),char(110),char(116),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(72),char(105),char(110),char(103),
-char(101),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),
-char(97),char(0),char(98),char(116),char(72),char(105),char(110),char(103),char(101),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(70),
-char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(72),char(105),char(110),char(103),char(101),char(67),char(111),char(110),char(115),
-char(116),char(114),char(97),char(105),char(110),char(116),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(50),char(0),char(98),char(116),
-char(67),char(111),char(110),char(101),char(84),char(119),char(105),char(115),char(116),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(68),
-char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(111),char(110),char(101),char(84),char(119),char(105),char(115),
-char(116),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(71),char(101),
+char(101),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),
+char(0),char(98),char(116),char(72),char(105),char(110),char(103),char(101),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(68),char(111),
+char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(50),char(0),char(98),char(116),char(67),char(111),char(110),char(101),char(84),char(119),char(105),char(115),
+char(116),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),
+char(97),char(0),char(98),char(116),char(67),char(111),char(110),char(101),char(84),char(119),char(105),char(115),char(116),char(67),char(111),char(110),char(115),char(116),char(114),char(97),
+char(105),char(110),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(71),char(101),char(110),char(101),char(114),char(105),char(99),char(54),char(68),char(111),
+char(102),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(71),char(101),
char(110),char(101),char(114),char(105),char(99),char(54),char(68),char(111),char(102),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(68),
-char(97),char(116),char(97),char(0),char(98),char(116),char(71),char(101),char(110),char(101),char(114),char(105),char(99),char(54),char(68),char(111),char(102),char(67),char(111),char(110),
-char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(50),char(0),char(98),
-char(116),char(71),char(101),char(110),char(101),char(114),char(105),char(99),char(54),char(68),char(111),char(102),char(83),char(112),char(114),char(105),char(110),char(103),char(67),char(111),
-char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(71),char(101),char(110),char(101),char(114),
-char(105),char(99),char(54),char(68),char(111),char(102),char(83),char(112),char(114),char(105),char(110),char(103),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),
-char(110),char(116),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(50),char(0),char(98),char(116),char(71),char(101),char(110),char(101),
-char(114),char(105),char(99),char(54),char(68),char(111),char(102),char(83),char(112),char(114),char(105),char(110),char(103),char(50),char(67),char(111),char(110),char(115),char(116),char(114),
-char(97),char(105),char(110),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(71),char(101),char(110),char(101),char(114),char(105),char(99),char(54),char(68),
-char(111),char(102),char(83),char(112),char(114),char(105),char(110),char(103),char(50),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(68),
-char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(50),char(0),char(98),char(116),char(83),char(108),char(105),char(100),char(101),char(114),char(67),
-char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(83),char(108),char(105),char(100),
-char(101),char(114),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),
-char(116),char(97),char(0),char(98),char(116),char(71),char(101),char(97),char(114),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(70),
-char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(71),char(101),char(97),char(114),char(67),char(111),char(110),char(115),char(116),
-char(114),char(97),char(105),char(110),char(116),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(83),char(111),char(102),char(116),
-char(66),char(111),char(100),char(121),char(77),char(97),char(116),char(101),char(114),char(105),char(97),char(108),char(68),char(97),char(116),char(97),char(0),char(83),char(111),char(102),
-char(116),char(66),char(111),char(100),char(121),char(78),char(111),char(100),char(101),char(68),char(97),char(116),char(97),char(0),char(83),char(111),char(102),char(116),char(66),char(111),
-char(100),char(121),char(76),char(105),char(110),char(107),char(68),char(97),char(116),char(97),char(0),char(83),char(111),char(102),char(116),char(66),char(111),char(100),char(121),char(70),
-char(97),char(99),char(101),char(68),char(97),char(116),char(97),char(0),char(83),char(111),char(102),char(116),char(66),char(111),char(100),char(121),char(84),char(101),char(116),char(114),
-char(97),char(68),char(97),char(116),char(97),char(0),char(83),char(111),char(102),char(116),char(82),char(105),char(103),char(105),char(100),char(65),char(110),char(99),char(104),char(111),
-char(114),char(68),char(97),char(116),char(97),char(0),char(83),char(111),char(102),char(116),char(66),char(111),char(100),char(121),char(67),char(111),char(110),char(102),char(105),char(103),
-char(68),char(97),char(116),char(97),char(0),char(83),char(111),char(102),char(116),char(66),char(111),char(100),char(121),char(80),char(111),char(115),char(101),char(68),char(97),char(116),
-char(97),char(0),char(83),char(111),char(102),char(116),char(66),char(111),char(100),char(121),char(67),char(108),char(117),char(115),char(116),char(101),char(114),char(68),char(97),char(116),
-char(97),char(0),char(98),char(116),char(83),char(111),char(102),char(116),char(66),char(111),char(100),char(121),char(74),char(111),char(105),char(110),char(116),char(68),char(97),char(116),
-char(97),char(0),char(98),char(116),char(83),char(111),char(102),char(116),char(66),char(111),char(100),char(121),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),
-char(97),char(0),char(98),char(116),char(77),char(117),char(108),char(116),char(105),char(66),char(111),char(100),char(121),char(76),char(105),char(110),char(107),char(68),char(111),char(117),
-char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(77),char(117),char(108),char(116),char(105),char(66),char(111),char(100),char(121),char(76),
-char(105),char(110),char(107),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(77),char(117),char(108),char(116),char(105),
-char(66),char(111),char(100),char(121),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(77),char(117),char(108),
-char(116),char(105),char(66),char(111),char(100),char(121),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(77),char(117),
-char(108),char(116),char(105),char(66),char(111),char(100),char(121),char(76),char(105),char(110),char(107),char(67),char(111),char(108),char(108),char(105),char(100),char(101),char(114),char(70),
-char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(77),char(117),char(108),char(116),char(105),char(66),char(111),char(100),char(121),
-char(76),char(105),char(110),char(107),char(67),char(111),char(108),char(108),char(105),char(100),char(101),char(114),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),
-char(116),char(97),char(0),char(0),char(84),char(76),char(69),char(78),char(1),char(0),char(1),char(0),char(2),char(0),char(2),char(0),char(4),char(0),char(4),char(0),
-char(4),char(0),char(4),char(0),char(8),char(0),char(0),char(0),char(12),char(0),char(36),char(0),char(8),char(0),char(16),char(0),char(32),char(0),char(16),char(0),
-char(32),char(0),char(48),char(0),char(96),char(0),char(64),char(0),char(-128),char(0),char(20),char(0),char(48),char(0),char(80),char(0),char(16),char(0),char(84),char(0),
-char(-124),char(0),char(12),char(0),char(52),char(0),char(52),char(0),char(20),char(0),char(64),char(0),char(4),char(0),char(4),char(0),char(8),char(0),char(4),char(0),
-char(32),char(0),char(28),char(0),char(60),char(0),char(56),char(0),char(76),char(0),char(76),char(0),char(24),char(0),char(60),char(0),char(60),char(0),char(60),char(0),
-char(16),char(0),char(-16),char(5),char(-24),char(1),char(56),char(3),char(16),char(1),char(64),char(0),char(68),char(0),char(-104),char(0),char(88),char(0),char(-72),char(0),
-char(104),char(0),char(-8),char(1),char(-72),char(3),char(8),char(0),char(52),char(0),char(52),char(0),char(0),char(0),char(68),char(0),char(84),char(0),char(-124),char(0),
-char(116),char(0),char(92),char(1),char(-36),char(0),char(-116),char(1),char(124),char(1),char(-44),char(0),char(-4),char(0),char(-52),char(1),char(92),char(1),char(116),char(2),
-char(-124),char(2),char(-76),char(4),char(-52),char(0),char(108),char(1),char(92),char(0),char(-116),char(0),char(16),char(0),char(100),char(0),char(20),char(0),char(36),char(0),
-char(100),char(0),char(92),char(0),char(104),char(0),char(-64),char(0),char(92),char(1),char(104),char(0),char(-68),char(1),char(112),char(3),char(-56),char(1),char(-68),char(0),
-char(100),char(0),char(28),char(1),char(-12),char(1),char(0),char(0),char(83),char(84),char(82),char(67),char(88),char(0),char(0),char(0),char(10),char(0),char(3),char(0),
-char(4),char(0),char(0),char(0),char(4),char(0),char(1),char(0),char(9),char(0),char(2),char(0),char(11),char(0),char(3),char(0),char(10),char(0),char(3),char(0),
-char(10),char(0),char(4),char(0),char(10),char(0),char(5),char(0),char(12),char(0),char(2),char(0),char(9),char(0),char(6),char(0),char(9),char(0),char(7),char(0),
-char(13),char(0),char(1),char(0),char(7),char(0),char(8),char(0),char(14),char(0),char(1),char(0),char(8),char(0),char(8),char(0),char(15),char(0),char(1),char(0),
-char(7),char(0),char(8),char(0),char(16),char(0),char(1),char(0),char(8),char(0),char(8),char(0),char(17),char(0),char(1),char(0),char(13),char(0),char(9),char(0),
-char(18),char(0),char(1),char(0),char(14),char(0),char(9),char(0),char(19),char(0),char(2),char(0),char(17),char(0),char(10),char(0),char(13),char(0),char(11),char(0),
-char(20),char(0),char(2),char(0),char(18),char(0),char(10),char(0),char(14),char(0),char(11),char(0),char(21),char(0),char(4),char(0),char(4),char(0),char(12),char(0),
-char(4),char(0),char(13),char(0),char(2),char(0),char(14),char(0),char(2),char(0),char(15),char(0),char(22),char(0),char(6),char(0),char(13),char(0),char(16),char(0),
-char(13),char(0),char(17),char(0),char(4),char(0),char(18),char(0),char(4),char(0),char(19),char(0),char(4),char(0),char(20),char(0),char(0),char(0),char(21),char(0),
-char(23),char(0),char(6),char(0),char(14),char(0),char(16),char(0),char(14),char(0),char(17),char(0),char(4),char(0),char(18),char(0),char(4),char(0),char(19),char(0),
-char(4),char(0),char(20),char(0),char(0),char(0),char(21),char(0),char(24),char(0),char(3),char(0),char(2),char(0),char(14),char(0),char(2),char(0),char(15),char(0),
-char(4),char(0),char(22),char(0),char(25),char(0),char(12),char(0),char(13),char(0),char(23),char(0),char(13),char(0),char(24),char(0),char(13),char(0),char(25),char(0),
-char(4),char(0),char(26),char(0),char(4),char(0),char(27),char(0),char(4),char(0),char(28),char(0),char(4),char(0),char(29),char(0),char(22),char(0),char(30),char(0),
-char(24),char(0),char(31),char(0),char(21),char(0),char(32),char(0),char(4),char(0),char(33),char(0),char(4),char(0),char(34),char(0),char(26),char(0),char(12),char(0),
-char(14),char(0),char(23),char(0),char(14),char(0),char(24),char(0),char(14),char(0),char(25),char(0),char(4),char(0),char(26),char(0),char(4),char(0),char(27),char(0),
-char(4),char(0),char(28),char(0),char(4),char(0),char(29),char(0),char(23),char(0),char(30),char(0),char(24),char(0),char(31),char(0),char(4),char(0),char(33),char(0),
-char(4),char(0),char(34),char(0),char(21),char(0),char(32),char(0),char(27),char(0),char(3),char(0),char(0),char(0),char(35),char(0),char(4),char(0),char(36),char(0),
-char(0),char(0),char(37),char(0),char(28),char(0),char(5),char(0),char(27),char(0),char(38),char(0),char(13),char(0),char(39),char(0),char(13),char(0),char(40),char(0),
-char(7),char(0),char(41),char(0),char(0),char(0),char(21),char(0),char(29),char(0),char(5),char(0),char(27),char(0),char(38),char(0),char(13),char(0),char(39),char(0),
-char(13),char(0),char(42),char(0),char(7),char(0),char(43),char(0),char(4),char(0),char(44),char(0),char(30),char(0),char(2),char(0),char(13),char(0),char(45),char(0),
-char(7),char(0),char(46),char(0),char(31),char(0),char(4),char(0),char(29),char(0),char(47),char(0),char(30),char(0),char(48),char(0),char(4),char(0),char(49),char(0),
-char(0),char(0),char(37),char(0),char(32),char(0),char(1),char(0),char(4),char(0),char(50),char(0),char(33),char(0),char(2),char(0),char(2),char(0),char(50),char(0),
-char(0),char(0),char(51),char(0),char(34),char(0),char(2),char(0),char(2),char(0),char(52),char(0),char(0),char(0),char(51),char(0),char(35),char(0),char(2),char(0),
-char(0),char(0),char(52),char(0),char(0),char(0),char(53),char(0),char(36),char(0),char(8),char(0),char(13),char(0),char(54),char(0),char(14),char(0),char(55),char(0),
-char(32),char(0),char(56),char(0),char(34),char(0),char(57),char(0),char(35),char(0),char(58),char(0),char(33),char(0),char(59),char(0),char(4),char(0),char(60),char(0),
-char(4),char(0),char(61),char(0),char(37),char(0),char(4),char(0),char(36),char(0),char(62),char(0),char(13),char(0),char(63),char(0),char(4),char(0),char(64),char(0),
-char(0),char(0),char(37),char(0),char(38),char(0),char(7),char(0),char(27),char(0),char(38),char(0),char(37),char(0),char(65),char(0),char(25),char(0),char(66),char(0),
-char(26),char(0),char(67),char(0),char(39),char(0),char(68),char(0),char(7),char(0),char(43),char(0),char(0),char(0),char(69),char(0),char(40),char(0),char(2),char(0),
-char(38),char(0),char(70),char(0),char(13),char(0),char(39),char(0),char(41),char(0),char(4),char(0),char(19),char(0),char(71),char(0),char(27),char(0),char(72),char(0),
-char(4),char(0),char(73),char(0),char(7),char(0),char(74),char(0),char(42),char(0),char(4),char(0),char(27),char(0),char(38),char(0),char(41),char(0),char(75),char(0),
-char(4),char(0),char(76),char(0),char(7),char(0),char(43),char(0),char(43),char(0),char(3),char(0),char(29),char(0),char(47),char(0),char(4),char(0),char(77),char(0),
-char(0),char(0),char(37),char(0),char(44),char(0),char(3),char(0),char(29),char(0),char(47),char(0),char(4),char(0),char(78),char(0),char(0),char(0),char(37),char(0),
-char(45),char(0),char(3),char(0),char(29),char(0),char(47),char(0),char(4),char(0),char(77),char(0),char(0),char(0),char(37),char(0),char(46),char(0),char(4),char(0),
-char(4),char(0),char(79),char(0),char(7),char(0),char(80),char(0),char(7),char(0),char(81),char(0),char(7),char(0),char(82),char(0),char(39),char(0),char(14),char(0),
-char(4),char(0),char(83),char(0),char(4),char(0),char(84),char(0),char(46),char(0),char(85),char(0),char(4),char(0),char(86),char(0),char(7),char(0),char(87),char(0),
-char(7),char(0),char(88),char(0),char(7),char(0),char(89),char(0),char(7),char(0),char(90),char(0),char(7),char(0),char(91),char(0),char(4),char(0),char(92),char(0),
-char(4),char(0),char(93),char(0),char(4),char(0),char(94),char(0),char(4),char(0),char(95),char(0),char(0),char(0),char(37),char(0),char(47),char(0),char(38),char(0),
-char(14),char(0),char(96),char(0),char(14),char(0),char(97),char(0),char(14),char(0),char(98),char(0),char(14),char(0),char(99),char(0),char(14),char(0),char(100),char(0),
-char(14),char(0),char(101),char(0),char(14),char(0),char(102),char(0),char(8),char(0),char(103),char(0),char(8),char(0),char(104),char(0),char(8),char(0),char(105),char(0),
-char(8),char(0),char(106),char(0),char(8),char(0),char(107),char(0),char(8),char(0),char(108),char(0),char(4),char(0),char(109),char(0),char(4),char(0),char(110),char(0),
-char(4),char(0),char(111),char(0),char(4),char(0),char(112),char(0),char(4),char(0),char(113),char(0),char(8),char(0),char(114),char(0),char(8),char(0),char(115),char(0),
-char(8),char(0),char(116),char(0),char(8),char(0),char(117),char(0),char(8),char(0),char(118),char(0),char(8),char(0),char(119),char(0),char(8),char(0),char(120),char(0),
-char(8),char(0),char(121),char(0),char(8),char(0),char(122),char(0),char(4),char(0),char(123),char(0),char(4),char(0),char(124),char(0),char(4),char(0),char(125),char(0),
-char(4),char(0),char(126),char(0),char(4),char(0),char(127),char(0),char(4),char(0),char(-128),char(0),char(8),char(0),char(-127),char(0),char(8),char(0),char(-126),char(0),
-char(4),char(0),char(44),char(0),char(48),char(0),char(-125),char(0),char(48),char(0),char(-124),char(0),char(49),char(0),char(38),char(0),char(13),char(0),char(96),char(0),
-char(13),char(0),char(97),char(0),char(13),char(0),char(98),char(0),char(13),char(0),char(99),char(0),char(13),char(0),char(100),char(0),char(13),char(0),char(101),char(0),
-char(13),char(0),char(102),char(0),char(7),char(0),char(103),char(0),char(7),char(0),char(104),char(0),char(7),char(0),char(105),char(0),char(7),char(0),char(106),char(0),
-char(7),char(0),char(107),char(0),char(7),char(0),char(108),char(0),char(4),char(0),char(109),char(0),char(4),char(0),char(110),char(0),char(4),char(0),char(111),char(0),
-char(4),char(0),char(112),char(0),char(4),char(0),char(113),char(0),char(7),char(0),char(114),char(0),char(7),char(0),char(115),char(0),char(7),char(0),char(116),char(0),
-char(7),char(0),char(117),char(0),char(7),char(0),char(118),char(0),char(7),char(0),char(119),char(0),char(7),char(0),char(120),char(0),char(7),char(0),char(121),char(0),
-char(7),char(0),char(122),char(0),char(4),char(0),char(123),char(0),char(4),char(0),char(124),char(0),char(4),char(0),char(125),char(0),char(4),char(0),char(126),char(0),
-char(4),char(0),char(127),char(0),char(4),char(0),char(-128),char(0),char(7),char(0),char(-127),char(0),char(7),char(0),char(-126),char(0),char(4),char(0),char(44),char(0),
-char(50),char(0),char(-125),char(0),char(50),char(0),char(-124),char(0),char(51),char(0),char(5),char(0),char(27),char(0),char(38),char(0),char(37),char(0),char(65),char(0),
-char(13),char(0),char(39),char(0),char(7),char(0),char(43),char(0),char(4),char(0),char(-123),char(0),char(52),char(0),char(5),char(0),char(29),char(0),char(47),char(0),
-char(13),char(0),char(-122),char(0),char(14),char(0),char(-121),char(0),char(4),char(0),char(-120),char(0),char(0),char(0),char(-119),char(0),char(48),char(0),char(29),char(0),
-char(9),char(0),char(-118),char(0),char(9),char(0),char(-117),char(0),char(27),char(0),char(-116),char(0),char(0),char(0),char(35),char(0),char(20),char(0),char(-115),char(0),
-char(20),char(0),char(-114),char(0),char(14),char(0),char(-113),char(0),char(14),char(0),char(-112),char(0),char(14),char(0),char(-111),char(0),char(8),char(0),char(-126),char(0),
-char(8),char(0),char(-110),char(0),char(8),char(0),char(-109),char(0),char(8),char(0),char(-108),char(0),char(8),char(0),char(-107),char(0),char(8),char(0),char(-106),char(0),
-char(8),char(0),char(-105),char(0),char(8),char(0),char(-104),char(0),char(8),char(0),char(-103),char(0),char(8),char(0),char(-102),char(0),char(4),char(0),char(-101),char(0),
-char(4),char(0),char(-100),char(0),char(4),char(0),char(-99),char(0),char(4),char(0),char(-98),char(0),char(4),char(0),char(-97),char(0),char(4),char(0),char(-96),char(0),
-char(4),char(0),char(-95),char(0),char(4),char(0),char(-94),char(0),char(4),char(0),char(-93),char(0),char(4),char(0),char(-92),char(0),char(50),char(0),char(29),char(0),
-char(9),char(0),char(-118),char(0),char(9),char(0),char(-117),char(0),char(27),char(0),char(-116),char(0),char(0),char(0),char(35),char(0),char(19),char(0),char(-115),char(0),
-char(19),char(0),char(-114),char(0),char(13),char(0),char(-113),char(0),char(13),char(0),char(-112),char(0),char(13),char(0),char(-111),char(0),char(7),char(0),char(-126),char(0),
-char(7),char(0),char(-110),char(0),char(7),char(0),char(-109),char(0),char(7),char(0),char(-108),char(0),char(7),char(0),char(-107),char(0),char(7),char(0),char(-106),char(0),
-char(7),char(0),char(-105),char(0),char(7),char(0),char(-104),char(0),char(7),char(0),char(-103),char(0),char(7),char(0),char(-102),char(0),char(4),char(0),char(-101),char(0),
-char(4),char(0),char(-100),char(0),char(4),char(0),char(-99),char(0),char(4),char(0),char(-98),char(0),char(4),char(0),char(-97),char(0),char(4),char(0),char(-96),char(0),
-char(4),char(0),char(-95),char(0),char(4),char(0),char(-94),char(0),char(4),char(0),char(-93),char(0),char(4),char(0),char(-92),char(0),char(53),char(0),char(22),char(0),
-char(8),char(0),char(-91),char(0),char(8),char(0),char(-90),char(0),char(8),char(0),char(-109),char(0),char(8),char(0),char(-89),char(0),char(8),char(0),char(-105),char(0),
-char(8),char(0),char(-88),char(0),char(8),char(0),char(-87),char(0),char(8),char(0),char(-86),char(0),char(8),char(0),char(-85),char(0),char(8),char(0),char(-84),char(0),
-char(8),char(0),char(-83),char(0),char(8),char(0),char(-82),char(0),char(8),char(0),char(-81),char(0),char(8),char(0),char(-80),char(0),char(8),char(0),char(-79),char(0),
-char(8),char(0),char(-78),char(0),char(4),char(0),char(-77),char(0),char(4),char(0),char(-76),char(0),char(4),char(0),char(-75),char(0),char(4),char(0),char(-74),char(0),
-char(4),char(0),char(-73),char(0),char(0),char(0),char(37),char(0),char(54),char(0),char(22),char(0),char(7),char(0),char(-91),char(0),char(7),char(0),char(-90),char(0),
-char(7),char(0),char(-109),char(0),char(7),char(0),char(-89),char(0),char(7),char(0),char(-105),char(0),char(7),char(0),char(-88),char(0),char(7),char(0),char(-87),char(0),
+char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(50),char(0),char(98),char(116),char(71),char(101),char(110),char(101),char(114),char(105),char(99),
+char(54),char(68),char(111),char(102),char(83),char(112),char(114),char(105),char(110),char(103),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),
+char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(71),char(101),char(110),char(101),char(114),char(105),char(99),char(54),char(68),char(111),char(102),char(83),char(112),
+char(114),char(105),char(110),char(103),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(68),char(111),char(117),char(98),char(108),char(101),
+char(68),char(97),char(116),char(97),char(50),char(0),char(98),char(116),char(71),char(101),char(110),char(101),char(114),char(105),char(99),char(54),char(68),char(111),char(102),char(83),
+char(112),char(114),char(105),char(110),char(103),char(50),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(68),char(97),char(116),char(97),
+char(0),char(98),char(116),char(71),char(101),char(110),char(101),char(114),char(105),char(99),char(54),char(68),char(111),char(102),char(83),char(112),char(114),char(105),char(110),char(103),
+char(50),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),
+char(97),char(50),char(0),char(98),char(116),char(83),char(108),char(105),char(100),char(101),char(114),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),
+char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(83),char(108),char(105),char(100),char(101),char(114),char(67),char(111),char(110),char(115),char(116),char(114),
+char(97),char(105),char(110),char(116),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(71),char(101),char(97),
+char(114),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),
+char(0),char(98),char(116),char(71),char(101),char(97),char(114),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(68),char(111),char(117),
+char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(83),char(111),char(102),char(116),char(66),char(111),char(100),char(121),char(77),char(97),char(116),char(101),
+char(114),char(105),char(97),char(108),char(68),char(97),char(116),char(97),char(0),char(83),char(111),char(102),char(116),char(66),char(111),char(100),char(121),char(78),char(111),char(100),
+char(101),char(68),char(97),char(116),char(97),char(0),char(83),char(111),char(102),char(116),char(66),char(111),char(100),char(121),char(76),char(105),char(110),char(107),char(68),char(97),
+char(116),char(97),char(0),char(83),char(111),char(102),char(116),char(66),char(111),char(100),char(121),char(70),char(97),char(99),char(101),char(68),char(97),char(116),char(97),char(0),
+char(83),char(111),char(102),char(116),char(66),char(111),char(100),char(121),char(84),char(101),char(116),char(114),char(97),char(68),char(97),char(116),char(97),char(0),char(83),char(111),
+char(102),char(116),char(82),char(105),char(103),char(105),char(100),char(65),char(110),char(99),char(104),char(111),char(114),char(68),char(97),char(116),char(97),char(0),char(83),char(111),
+char(102),char(116),char(66),char(111),char(100),char(121),char(67),char(111),char(110),char(102),char(105),char(103),char(68),char(97),char(116),char(97),char(0),char(83),char(111),char(102),
+char(116),char(66),char(111),char(100),char(121),char(80),char(111),char(115),char(101),char(68),char(97),char(116),char(97),char(0),char(83),char(111),char(102),char(116),char(66),char(111),
+char(100),char(121),char(67),char(108),char(117),char(115),char(116),char(101),char(114),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(83),char(111),char(102),char(116),
+char(66),char(111),char(100),char(121),char(74),char(111),char(105),char(110),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(83),char(111),char(102),char(116),
+char(66),char(111),char(100),char(121),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(77),char(117),char(108),char(116),
+char(105),char(66),char(111),char(100),char(121),char(76),char(105),char(110),char(107),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),
+char(98),char(116),char(77),char(117),char(108),char(116),char(105),char(66),char(111),char(100),char(121),char(76),char(105),char(110),char(107),char(70),char(108),char(111),char(97),char(116),
+char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(77),char(117),char(108),char(116),char(105),char(66),char(111),char(100),char(121),char(68),char(111),char(117),char(98),
+char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(77),char(117),char(108),char(116),char(105),char(66),char(111),char(100),char(121),char(70),char(108),
+char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(77),char(117),char(108),char(116),char(105),char(66),char(111),char(100),char(121),char(76),
+char(105),char(110),char(107),char(67),char(111),char(108),char(108),char(105),char(100),char(101),char(114),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),
+char(0),char(98),char(116),char(77),char(117),char(108),char(116),char(105),char(66),char(111),char(100),char(121),char(76),char(105),char(110),char(107),char(67),char(111),char(108),char(108),
+char(105),char(100),char(101),char(114),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(0),char(84),char(76),char(69),char(78),
+char(1),char(0),char(1),char(0),char(2),char(0),char(2),char(0),char(4),char(0),char(4),char(0),char(4),char(0),char(4),char(0),char(8),char(0),char(0),char(0),
+char(12),char(0),char(36),char(0),char(8),char(0),char(16),char(0),char(32),char(0),char(16),char(0),char(32),char(0),char(48),char(0),char(96),char(0),char(64),char(0),
+char(-128),char(0),char(20),char(0),char(48),char(0),char(80),char(0),char(16),char(0),char(84),char(0),char(-124),char(0),char(12),char(0),char(52),char(0),char(52),char(0),
+char(20),char(0),char(64),char(0),char(4),char(0),char(4),char(0),char(8),char(0),char(4),char(0),char(32),char(0),char(28),char(0),char(60),char(0),char(56),char(0),
+char(76),char(0),char(76),char(0),char(24),char(0),char(60),char(0),char(60),char(0),char(60),char(0),char(16),char(0),char(16),char(6),char(-24),char(1),char(72),char(3),
+char(16),char(1),char(64),char(0),char(68),char(0),char(-96),char(0),char(88),char(0),char(-64),char(0),char(104),char(0),char(-8),char(1),char(-72),char(3),char(8),char(0),
+char(52),char(0),char(52),char(0),char(0),char(0),char(68),char(0),char(84),char(0),char(-124),char(0),char(116),char(0),char(92),char(1),char(-36),char(0),char(-116),char(1),
+char(124),char(1),char(-44),char(0),char(-4),char(0),char(-52),char(1),char(92),char(1),char(116),char(2),char(-124),char(2),char(-76),char(4),char(-52),char(0),char(108),char(1),
+char(92),char(0),char(-116),char(0),char(16),char(0),char(100),char(0),char(20),char(0),char(36),char(0),char(100),char(0),char(92),char(0),char(104),char(0),char(-64),char(0),
+char(92),char(1),char(104),char(0),char(-68),char(1),char(112),char(3),char(-56),char(1),char(-68),char(0),char(100),char(0),char(28),char(1),char(-12),char(1),char(0),char(0),
+char(83),char(84),char(82),char(67),char(88),char(0),char(0),char(0),char(10),char(0),char(3),char(0),char(4),char(0),char(0),char(0),char(4),char(0),char(1),char(0),
+char(9),char(0),char(2),char(0),char(11),char(0),char(3),char(0),char(10),char(0),char(3),char(0),char(10),char(0),char(4),char(0),char(10),char(0),char(5),char(0),
+char(12),char(0),char(2),char(0),char(9),char(0),char(6),char(0),char(9),char(0),char(7),char(0),char(13),char(0),char(1),char(0),char(7),char(0),char(8),char(0),
+char(14),char(0),char(1),char(0),char(8),char(0),char(8),char(0),char(15),char(0),char(1),char(0),char(7),char(0),char(8),char(0),char(16),char(0),char(1),char(0),
+char(8),char(0),char(8),char(0),char(17),char(0),char(1),char(0),char(13),char(0),char(9),char(0),char(18),char(0),char(1),char(0),char(14),char(0),char(9),char(0),
+char(19),char(0),char(2),char(0),char(17),char(0),char(10),char(0),char(13),char(0),char(11),char(0),char(20),char(0),char(2),char(0),char(18),char(0),char(10),char(0),
+char(14),char(0),char(11),char(0),char(21),char(0),char(4),char(0),char(4),char(0),char(12),char(0),char(4),char(0),char(13),char(0),char(2),char(0),char(14),char(0),
+char(2),char(0),char(15),char(0),char(22),char(0),char(6),char(0),char(13),char(0),char(16),char(0),char(13),char(0),char(17),char(0),char(4),char(0),char(18),char(0),
+char(4),char(0),char(19),char(0),char(4),char(0),char(20),char(0),char(0),char(0),char(21),char(0),char(23),char(0),char(6),char(0),char(14),char(0),char(16),char(0),
+char(14),char(0),char(17),char(0),char(4),char(0),char(18),char(0),char(4),char(0),char(19),char(0),char(4),char(0),char(20),char(0),char(0),char(0),char(21),char(0),
+char(24),char(0),char(3),char(0),char(2),char(0),char(14),char(0),char(2),char(0),char(15),char(0),char(4),char(0),char(22),char(0),char(25),char(0),char(12),char(0),
+char(13),char(0),char(23),char(0),char(13),char(0),char(24),char(0),char(13),char(0),char(25),char(0),char(4),char(0),char(26),char(0),char(4),char(0),char(27),char(0),
+char(4),char(0),char(28),char(0),char(4),char(0),char(29),char(0),char(22),char(0),char(30),char(0),char(24),char(0),char(31),char(0),char(21),char(0),char(32),char(0),
+char(4),char(0),char(33),char(0),char(4),char(0),char(34),char(0),char(26),char(0),char(12),char(0),char(14),char(0),char(23),char(0),char(14),char(0),char(24),char(0),
+char(14),char(0),char(25),char(0),char(4),char(0),char(26),char(0),char(4),char(0),char(27),char(0),char(4),char(0),char(28),char(0),char(4),char(0),char(29),char(0),
+char(23),char(0),char(30),char(0),char(24),char(0),char(31),char(0),char(4),char(0),char(33),char(0),char(4),char(0),char(34),char(0),char(21),char(0),char(32),char(0),
+char(27),char(0),char(3),char(0),char(0),char(0),char(35),char(0),char(4),char(0),char(36),char(0),char(0),char(0),char(37),char(0),char(28),char(0),char(5),char(0),
+char(27),char(0),char(38),char(0),char(13),char(0),char(39),char(0),char(13),char(0),char(40),char(0),char(7),char(0),char(41),char(0),char(0),char(0),char(21),char(0),
+char(29),char(0),char(5),char(0),char(27),char(0),char(38),char(0),char(13),char(0),char(39),char(0),char(13),char(0),char(42),char(0),char(7),char(0),char(43),char(0),
+char(4),char(0),char(44),char(0),char(30),char(0),char(2),char(0),char(13),char(0),char(45),char(0),char(7),char(0),char(46),char(0),char(31),char(0),char(4),char(0),
+char(29),char(0),char(47),char(0),char(30),char(0),char(48),char(0),char(4),char(0),char(49),char(0),char(0),char(0),char(37),char(0),char(32),char(0),char(1),char(0),
+char(4),char(0),char(50),char(0),char(33),char(0),char(2),char(0),char(2),char(0),char(50),char(0),char(0),char(0),char(51),char(0),char(34),char(0),char(2),char(0),
+char(2),char(0),char(52),char(0),char(0),char(0),char(51),char(0),char(35),char(0),char(2),char(0),char(0),char(0),char(52),char(0),char(0),char(0),char(53),char(0),
+char(36),char(0),char(8),char(0),char(13),char(0),char(54),char(0),char(14),char(0),char(55),char(0),char(32),char(0),char(56),char(0),char(34),char(0),char(57),char(0),
+char(35),char(0),char(58),char(0),char(33),char(0),char(59),char(0),char(4),char(0),char(60),char(0),char(4),char(0),char(61),char(0),char(37),char(0),char(4),char(0),
+char(36),char(0),char(62),char(0),char(13),char(0),char(63),char(0),char(4),char(0),char(64),char(0),char(0),char(0),char(37),char(0),char(38),char(0),char(7),char(0),
+char(27),char(0),char(38),char(0),char(37),char(0),char(65),char(0),char(25),char(0),char(66),char(0),char(26),char(0),char(67),char(0),char(39),char(0),char(68),char(0),
+char(7),char(0),char(43),char(0),char(0),char(0),char(69),char(0),char(40),char(0),char(2),char(0),char(38),char(0),char(70),char(0),char(13),char(0),char(39),char(0),
+char(41),char(0),char(4),char(0),char(19),char(0),char(71),char(0),char(27),char(0),char(72),char(0),char(4),char(0),char(73),char(0),char(7),char(0),char(74),char(0),
+char(42),char(0),char(4),char(0),char(27),char(0),char(38),char(0),char(41),char(0),char(75),char(0),char(4),char(0),char(76),char(0),char(7),char(0),char(43),char(0),
+char(43),char(0),char(3),char(0),char(29),char(0),char(47),char(0),char(4),char(0),char(77),char(0),char(0),char(0),char(37),char(0),char(44),char(0),char(3),char(0),
+char(29),char(0),char(47),char(0),char(4),char(0),char(78),char(0),char(0),char(0),char(37),char(0),char(45),char(0),char(3),char(0),char(29),char(0),char(47),char(0),
+char(4),char(0),char(77),char(0),char(0),char(0),char(37),char(0),char(46),char(0),char(4),char(0),char(4),char(0),char(79),char(0),char(7),char(0),char(80),char(0),
+char(7),char(0),char(81),char(0),char(7),char(0),char(82),char(0),char(39),char(0),char(14),char(0),char(4),char(0),char(83),char(0),char(4),char(0),char(84),char(0),
+char(46),char(0),char(85),char(0),char(4),char(0),char(86),char(0),char(7),char(0),char(87),char(0),char(7),char(0),char(88),char(0),char(7),char(0),char(89),char(0),
+char(7),char(0),char(90),char(0),char(7),char(0),char(91),char(0),char(4),char(0),char(92),char(0),char(4),char(0),char(93),char(0),char(4),char(0),char(94),char(0),
+char(4),char(0),char(95),char(0),char(0),char(0),char(37),char(0),char(47),char(0),char(39),char(0),char(14),char(0),char(96),char(0),char(14),char(0),char(97),char(0),
+char(14),char(0),char(98),char(0),char(14),char(0),char(99),char(0),char(14),char(0),char(100),char(0),char(14),char(0),char(101),char(0),char(14),char(0),char(102),char(0),
+char(8),char(0),char(103),char(0),char(8),char(0),char(104),char(0),char(8),char(0),char(105),char(0),char(8),char(0),char(106),char(0),char(8),char(0),char(107),char(0),
+char(8),char(0),char(108),char(0),char(8),char(0),char(109),char(0),char(4),char(0),char(110),char(0),char(4),char(0),char(111),char(0),char(4),char(0),char(112),char(0),
+char(4),char(0),char(113),char(0),char(4),char(0),char(114),char(0),char(8),char(0),char(115),char(0),char(8),char(0),char(116),char(0),char(8),char(0),char(117),char(0),
+char(8),char(0),char(118),char(0),char(8),char(0),char(119),char(0),char(8),char(0),char(120),char(0),char(8),char(0),char(121),char(0),char(8),char(0),char(122),char(0),
+char(8),char(0),char(123),char(0),char(4),char(0),char(124),char(0),char(4),char(0),char(125),char(0),char(4),char(0),char(126),char(0),char(4),char(0),char(127),char(0),
+char(4),char(0),char(-128),char(0),char(4),char(0),char(-127),char(0),char(8),char(0),char(-126),char(0),char(8),char(0),char(-125),char(0),char(4),char(0),char(44),char(0),
+char(48),char(0),char(-124),char(0),char(48),char(0),char(-123),char(0),char(49),char(0),char(39),char(0),char(13),char(0),char(96),char(0),char(13),char(0),char(97),char(0),
+char(13),char(0),char(98),char(0),char(13),char(0),char(99),char(0),char(13),char(0),char(100),char(0),char(13),char(0),char(101),char(0),char(13),char(0),char(102),char(0),
+char(7),char(0),char(103),char(0),char(7),char(0),char(104),char(0),char(7),char(0),char(105),char(0),char(7),char(0),char(106),char(0),char(7),char(0),char(107),char(0),
+char(7),char(0),char(108),char(0),char(7),char(0),char(109),char(0),char(4),char(0),char(110),char(0),char(4),char(0),char(111),char(0),char(4),char(0),char(112),char(0),
+char(4),char(0),char(113),char(0),char(4),char(0),char(114),char(0),char(7),char(0),char(115),char(0),char(7),char(0),char(116),char(0),char(7),char(0),char(117),char(0),
+char(7),char(0),char(118),char(0),char(7),char(0),char(119),char(0),char(7),char(0),char(120),char(0),char(7),char(0),char(121),char(0),char(7),char(0),char(122),char(0),
+char(7),char(0),char(123),char(0),char(4),char(0),char(124),char(0),char(4),char(0),char(125),char(0),char(4),char(0),char(126),char(0),char(4),char(0),char(127),char(0),
+char(4),char(0),char(-128),char(0),char(4),char(0),char(-127),char(0),char(7),char(0),char(-126),char(0),char(7),char(0),char(-125),char(0),char(4),char(0),char(44),char(0),
+char(50),char(0),char(-124),char(0),char(50),char(0),char(-123),char(0),char(51),char(0),char(5),char(0),char(27),char(0),char(38),char(0),char(37),char(0),char(65),char(0),
+char(13),char(0),char(39),char(0),char(7),char(0),char(43),char(0),char(4),char(0),char(-122),char(0),char(52),char(0),char(5),char(0),char(29),char(0),char(47),char(0),
+char(13),char(0),char(-121),char(0),char(14),char(0),char(-120),char(0),char(4),char(0),char(-119),char(0),char(0),char(0),char(-118),char(0),char(48),char(0),char(29),char(0),
+char(9),char(0),char(-117),char(0),char(9),char(0),char(-116),char(0),char(27),char(0),char(-115),char(0),char(0),char(0),char(35),char(0),char(20),char(0),char(-114),char(0),
+char(20),char(0),char(-113),char(0),char(14),char(0),char(-112),char(0),char(14),char(0),char(-111),char(0),char(14),char(0),char(-110),char(0),char(8),char(0),char(-125),char(0),
+char(8),char(0),char(-109),char(0),char(8),char(0),char(-108),char(0),char(8),char(0),char(-107),char(0),char(8),char(0),char(-106),char(0),char(8),char(0),char(-105),char(0),
+char(8),char(0),char(-104),char(0),char(8),char(0),char(-103),char(0),char(8),char(0),char(-102),char(0),char(8),char(0),char(-101),char(0),char(4),char(0),char(-100),char(0),
+char(4),char(0),char(-99),char(0),char(4),char(0),char(-98),char(0),char(4),char(0),char(-97),char(0),char(4),char(0),char(-96),char(0),char(4),char(0),char(-95),char(0),
+char(4),char(0),char(-94),char(0),char(4),char(0),char(-93),char(0),char(4),char(0),char(-92),char(0),char(4),char(0),char(-91),char(0),char(50),char(0),char(29),char(0),
+char(9),char(0),char(-117),char(0),char(9),char(0),char(-116),char(0),char(27),char(0),char(-115),char(0),char(0),char(0),char(35),char(0),char(19),char(0),char(-114),char(0),
+char(19),char(0),char(-113),char(0),char(13),char(0),char(-112),char(0),char(13),char(0),char(-111),char(0),char(13),char(0),char(-110),char(0),char(7),char(0),char(-125),char(0),
+char(7),char(0),char(-109),char(0),char(7),char(0),char(-108),char(0),char(7),char(0),char(-107),char(0),char(7),char(0),char(-106),char(0),char(7),char(0),char(-105),char(0),
+char(7),char(0),char(-104),char(0),char(7),char(0),char(-103),char(0),char(7),char(0),char(-102),char(0),char(7),char(0),char(-101),char(0),char(4),char(0),char(-100),char(0),
+char(4),char(0),char(-99),char(0),char(4),char(0),char(-98),char(0),char(4),char(0),char(-97),char(0),char(4),char(0),char(-96),char(0),char(4),char(0),char(-95),char(0),
+char(4),char(0),char(-94),char(0),char(4),char(0),char(-93),char(0),char(4),char(0),char(-92),char(0),char(4),char(0),char(-91),char(0),char(53),char(0),char(23),char(0),
+char(8),char(0),char(-90),char(0),char(8),char(0),char(-89),char(0),char(8),char(0),char(-108),char(0),char(8),char(0),char(-88),char(0),char(8),char(0),char(-104),char(0),
+char(8),char(0),char(-87),char(0),char(8),char(0),char(-86),char(0),char(8),char(0),char(-85),char(0),char(8),char(0),char(-84),char(0),char(8),char(0),char(-83),char(0),
+char(8),char(0),char(-82),char(0),char(8),char(0),char(-81),char(0),char(8),char(0),char(-80),char(0),char(8),char(0),char(-79),char(0),char(8),char(0),char(-78),char(0),
+char(8),char(0),char(-77),char(0),char(8),char(0),char(-76),char(0),char(4),char(0),char(-75),char(0),char(4),char(0),char(-74),char(0),char(4),char(0),char(-73),char(0),
+char(4),char(0),char(-72),char(0),char(4),char(0),char(-71),char(0),char(0),char(0),char(37),char(0),char(54),char(0),char(22),char(0),char(7),char(0),char(-90),char(0),
+char(7),char(0),char(-89),char(0),char(7),char(0),char(-108),char(0),char(7),char(0),char(-88),char(0),char(7),char(0),char(-104),char(0),char(7),char(0),char(-87),char(0),
char(7),char(0),char(-86),char(0),char(7),char(0),char(-85),char(0),char(7),char(0),char(-84),char(0),char(7),char(0),char(-83),char(0),char(7),char(0),char(-82),char(0),
-char(7),char(0),char(-81),char(0),char(7),char(0),char(-80),char(0),char(7),char(0),char(-79),char(0),char(7),char(0),char(-78),char(0),char(4),char(0),char(-77),char(0),
-char(4),char(0),char(-76),char(0),char(4),char(0),char(-75),char(0),char(4),char(0),char(-74),char(0),char(4),char(0),char(-73),char(0),char(0),char(0),char(37),char(0),
-char(55),char(0),char(2),char(0),char(53),char(0),char(-72),char(0),char(14),char(0),char(-71),char(0),char(56),char(0),char(2),char(0),char(54),char(0),char(-72),char(0),
-char(13),char(0),char(-71),char(0),char(57),char(0),char(21),char(0),char(50),char(0),char(-70),char(0),char(17),char(0),char(-69),char(0),char(13),char(0),char(-68),char(0),
-char(13),char(0),char(-67),char(0),char(13),char(0),char(-66),char(0),char(13),char(0),char(-65),char(0),char(13),char(0),char(-71),char(0),char(13),char(0),char(-64),char(0),
-char(13),char(0),char(-63),char(0),char(13),char(0),char(-62),char(0),char(13),char(0),char(-61),char(0),char(7),char(0),char(-60),char(0),char(7),char(0),char(-59),char(0),
-char(7),char(0),char(-58),char(0),char(7),char(0),char(-57),char(0),char(7),char(0),char(-56),char(0),char(7),char(0),char(-55),char(0),char(7),char(0),char(-54),char(0),
-char(7),char(0),char(-53),char(0),char(7),char(0),char(-52),char(0),char(4),char(0),char(-51),char(0),char(58),char(0),char(22),char(0),char(48),char(0),char(-70),char(0),
-char(18),char(0),char(-69),char(0),char(14),char(0),char(-68),char(0),char(14),char(0),char(-67),char(0),char(14),char(0),char(-66),char(0),char(14),char(0),char(-65),char(0),
-char(14),char(0),char(-71),char(0),char(14),char(0),char(-64),char(0),char(14),char(0),char(-63),char(0),char(14),char(0),char(-62),char(0),char(14),char(0),char(-61),char(0),
-char(8),char(0),char(-60),char(0),char(8),char(0),char(-59),char(0),char(8),char(0),char(-58),char(0),char(8),char(0),char(-57),char(0),char(8),char(0),char(-56),char(0),
-char(8),char(0),char(-55),char(0),char(8),char(0),char(-54),char(0),char(8),char(0),char(-53),char(0),char(8),char(0),char(-52),char(0),char(4),char(0),char(-51),char(0),
-char(0),char(0),char(37),char(0),char(59),char(0),char(2),char(0),char(4),char(0),char(-50),char(0),char(4),char(0),char(-49),char(0),char(60),char(0),char(13),char(0),
-char(57),char(0),char(-48),char(0),char(57),char(0),char(-47),char(0),char(0),char(0),char(35),char(0),char(4),char(0),char(-128),char(0),char(4),char(0),char(-46),char(0),
-char(4),char(0),char(-45),char(0),char(4),char(0),char(-44),char(0),char(7),char(0),char(-43),char(0),char(7),char(0),char(-42),char(0),char(4),char(0),char(-41),char(0),
-char(4),char(0),char(-40),char(0),char(7),char(0),char(-39),char(0),char(4),char(0),char(-38),char(0),char(61),char(0),char(13),char(0),char(62),char(0),char(-48),char(0),
-char(62),char(0),char(-47),char(0),char(0),char(0),char(35),char(0),char(4),char(0),char(-128),char(0),char(4),char(0),char(-46),char(0),char(4),char(0),char(-45),char(0),
-char(4),char(0),char(-44),char(0),char(7),char(0),char(-43),char(0),char(7),char(0),char(-42),char(0),char(4),char(0),char(-41),char(0),char(4),char(0),char(-40),char(0),
-char(7),char(0),char(-39),char(0),char(4),char(0),char(-38),char(0),char(63),char(0),char(14),char(0),char(58),char(0),char(-48),char(0),char(58),char(0),char(-47),char(0),
-char(0),char(0),char(35),char(0),char(4),char(0),char(-128),char(0),char(4),char(0),char(-46),char(0),char(4),char(0),char(-45),char(0),char(4),char(0),char(-44),char(0),
-char(8),char(0),char(-43),char(0),char(8),char(0),char(-42),char(0),char(4),char(0),char(-41),char(0),char(4),char(0),char(-40),char(0),char(8),char(0),char(-39),char(0),
-char(4),char(0),char(-38),char(0),char(0),char(0),char(-37),char(0),char(64),char(0),char(3),char(0),char(61),char(0),char(-36),char(0),char(13),char(0),char(-35),char(0),
-char(13),char(0),char(-34),char(0),char(65),char(0),char(3),char(0),char(63),char(0),char(-36),char(0),char(14),char(0),char(-35),char(0),char(14),char(0),char(-34),char(0),
-char(66),char(0),char(3),char(0),char(61),char(0),char(-36),char(0),char(14),char(0),char(-35),char(0),char(14),char(0),char(-34),char(0),char(67),char(0),char(13),char(0),
-char(61),char(0),char(-36),char(0),char(20),char(0),char(-33),char(0),char(20),char(0),char(-32),char(0),char(4),char(0),char(-31),char(0),char(4),char(0),char(-30),char(0),
-char(4),char(0),char(-29),char(0),char(7),char(0),char(-28),char(0),char(7),char(0),char(-27),char(0),char(7),char(0),char(-26),char(0),char(7),char(0),char(-25),char(0),
-char(7),char(0),char(-24),char(0),char(7),char(0),char(-23),char(0),char(7),char(0),char(-22),char(0),char(68),char(0),char(13),char(0),char(61),char(0),char(-36),char(0),
-char(19),char(0),char(-33),char(0),char(19),char(0),char(-32),char(0),char(4),char(0),char(-31),char(0),char(4),char(0),char(-30),char(0),char(4),char(0),char(-29),char(0),
-char(7),char(0),char(-28),char(0),char(7),char(0),char(-27),char(0),char(7),char(0),char(-26),char(0),char(7),char(0),char(-25),char(0),char(7),char(0),char(-24),char(0),
-char(7),char(0),char(-23),char(0),char(7),char(0),char(-22),char(0),char(69),char(0),char(14),char(0),char(63),char(0),char(-36),char(0),char(20),char(0),char(-33),char(0),
-char(20),char(0),char(-32),char(0),char(4),char(0),char(-31),char(0),char(4),char(0),char(-30),char(0),char(4),char(0),char(-29),char(0),char(8),char(0),char(-28),char(0),
-char(8),char(0),char(-27),char(0),char(8),char(0),char(-26),char(0),char(8),char(0),char(-25),char(0),char(8),char(0),char(-24),char(0),char(8),char(0),char(-23),char(0),
-char(8),char(0),char(-22),char(0),char(0),char(0),char(-21),char(0),char(70),char(0),char(10),char(0),char(63),char(0),char(-36),char(0),char(20),char(0),char(-33),char(0),
-char(20),char(0),char(-32),char(0),char(8),char(0),char(-20),char(0),char(8),char(0),char(-19),char(0),char(8),char(0),char(-18),char(0),char(8),char(0),char(-24),char(0),
-char(8),char(0),char(-23),char(0),char(8),char(0),char(-22),char(0),char(8),char(0),char(-90),char(0),char(71),char(0),char(11),char(0),char(61),char(0),char(-36),char(0),
-char(19),char(0),char(-33),char(0),char(19),char(0),char(-32),char(0),char(7),char(0),char(-20),char(0),char(7),char(0),char(-19),char(0),char(7),char(0),char(-18),char(0),
-char(7),char(0),char(-24),char(0),char(7),char(0),char(-23),char(0),char(7),char(0),char(-22),char(0),char(7),char(0),char(-90),char(0),char(0),char(0),char(21),char(0),
-char(72),char(0),char(9),char(0),char(61),char(0),char(-36),char(0),char(19),char(0),char(-33),char(0),char(19),char(0),char(-32),char(0),char(13),char(0),char(-17),char(0),
-char(13),char(0),char(-16),char(0),char(13),char(0),char(-15),char(0),char(13),char(0),char(-14),char(0),char(4),char(0),char(-13),char(0),char(4),char(0),char(-12),char(0),
-char(73),char(0),char(9),char(0),char(63),char(0),char(-36),char(0),char(20),char(0),char(-33),char(0),char(20),char(0),char(-32),char(0),char(14),char(0),char(-17),char(0),
-char(14),char(0),char(-16),char(0),char(14),char(0),char(-15),char(0),char(14),char(0),char(-14),char(0),char(4),char(0),char(-13),char(0),char(4),char(0),char(-12),char(0),
-char(74),char(0),char(5),char(0),char(72),char(0),char(-11),char(0),char(4),char(0),char(-10),char(0),char(7),char(0),char(-9),char(0),char(7),char(0),char(-8),char(0),
-char(7),char(0),char(-7),char(0),char(75),char(0),char(5),char(0),char(73),char(0),char(-11),char(0),char(4),char(0),char(-10),char(0),char(8),char(0),char(-9),char(0),
-char(8),char(0),char(-8),char(0),char(8),char(0),char(-7),char(0),char(76),char(0),char(41),char(0),char(61),char(0),char(-36),char(0),char(19),char(0),char(-33),char(0),
-char(19),char(0),char(-32),char(0),char(13),char(0),char(-17),char(0),char(13),char(0),char(-16),char(0),char(13),char(0),char(-6),char(0),char(13),char(0),char(-5),char(0),
-char(13),char(0),char(-4),char(0),char(13),char(0),char(-3),char(0),char(13),char(0),char(-2),char(0),char(13),char(0),char(-1),char(0),char(13),char(0),char(0),char(1),
-char(13),char(0),char(1),char(1),char(13),char(0),char(2),char(1),char(13),char(0),char(3),char(1),char(13),char(0),char(4),char(1),char(0),char(0),char(5),char(1),
-char(0),char(0),char(6),char(1),char(0),char(0),char(7),char(1),char(0),char(0),char(8),char(1),char(0),char(0),char(9),char(1),char(0),char(0),char(-21),char(0),
-char(13),char(0),char(-15),char(0),char(13),char(0),char(-14),char(0),char(13),char(0),char(10),char(1),char(13),char(0),char(11),char(1),char(13),char(0),char(12),char(1),
-char(13),char(0),char(13),char(1),char(13),char(0),char(14),char(1),char(13),char(0),char(15),char(1),char(13),char(0),char(16),char(1),char(13),char(0),char(17),char(1),
-char(13),char(0),char(18),char(1),char(13),char(0),char(19),char(1),char(13),char(0),char(20),char(1),char(0),char(0),char(21),char(1),char(0),char(0),char(22),char(1),
-char(0),char(0),char(23),char(1),char(0),char(0),char(24),char(1),char(0),char(0),char(25),char(1),char(4),char(0),char(26),char(1),char(77),char(0),char(41),char(0),
-char(63),char(0),char(-36),char(0),char(20),char(0),char(-33),char(0),char(20),char(0),char(-32),char(0),char(14),char(0),char(-17),char(0),char(14),char(0),char(-16),char(0),
-char(14),char(0),char(-6),char(0),char(14),char(0),char(-5),char(0),char(14),char(0),char(-4),char(0),char(14),char(0),char(-3),char(0),char(14),char(0),char(-2),char(0),
-char(14),char(0),char(-1),char(0),char(14),char(0),char(0),char(1),char(14),char(0),char(1),char(1),char(14),char(0),char(2),char(1),char(14),char(0),char(3),char(1),
-char(14),char(0),char(4),char(1),char(0),char(0),char(5),char(1),char(0),char(0),char(6),char(1),char(0),char(0),char(7),char(1),char(0),char(0),char(8),char(1),
-char(0),char(0),char(9),char(1),char(0),char(0),char(-21),char(0),char(14),char(0),char(-15),char(0),char(14),char(0),char(-14),char(0),char(14),char(0),char(10),char(1),
-char(14),char(0),char(11),char(1),char(14),char(0),char(12),char(1),char(14),char(0),char(13),char(1),char(14),char(0),char(14),char(1),char(14),char(0),char(15),char(1),
-char(14),char(0),char(16),char(1),char(14),char(0),char(17),char(1),char(14),char(0),char(18),char(1),char(14),char(0),char(19),char(1),char(14),char(0),char(20),char(1),
-char(0),char(0),char(21),char(1),char(0),char(0),char(22),char(1),char(0),char(0),char(23),char(1),char(0),char(0),char(24),char(1),char(0),char(0),char(25),char(1),
-char(4),char(0),char(26),char(1),char(78),char(0),char(9),char(0),char(61),char(0),char(-36),char(0),char(19),char(0),char(-33),char(0),char(19),char(0),char(-32),char(0),
-char(7),char(0),char(-17),char(0),char(7),char(0),char(-16),char(0),char(7),char(0),char(-15),char(0),char(7),char(0),char(-14),char(0),char(4),char(0),char(-13),char(0),
-char(4),char(0),char(-12),char(0),char(79),char(0),char(9),char(0),char(63),char(0),char(-36),char(0),char(20),char(0),char(-33),char(0),char(20),char(0),char(-32),char(0),
-char(8),char(0),char(-17),char(0),char(8),char(0),char(-16),char(0),char(8),char(0),char(-15),char(0),char(8),char(0),char(-14),char(0),char(4),char(0),char(-13),char(0),
-char(4),char(0),char(-12),char(0),char(80),char(0),char(5),char(0),char(60),char(0),char(-36),char(0),char(13),char(0),char(27),char(1),char(13),char(0),char(28),char(1),
-char(7),char(0),char(29),char(1),char(0),char(0),char(37),char(0),char(81),char(0),char(4),char(0),char(63),char(0),char(-36),char(0),char(14),char(0),char(27),char(1),
-char(14),char(0),char(28),char(1),char(8),char(0),char(29),char(1),char(82),char(0),char(4),char(0),char(7),char(0),char(30),char(1),char(7),char(0),char(31),char(1),
-char(7),char(0),char(32),char(1),char(4),char(0),char(79),char(0),char(83),char(0),char(10),char(0),char(82),char(0),char(33),char(1),char(13),char(0),char(34),char(1),
-char(13),char(0),char(35),char(1),char(13),char(0),char(36),char(1),char(13),char(0),char(37),char(1),char(13),char(0),char(38),char(1),char(7),char(0),char(-60),char(0),
-char(7),char(0),char(39),char(1),char(4),char(0),char(40),char(1),char(4),char(0),char(53),char(0),char(84),char(0),char(4),char(0),char(82),char(0),char(33),char(1),
-char(4),char(0),char(41),char(1),char(7),char(0),char(42),char(1),char(4),char(0),char(43),char(1),char(85),char(0),char(4),char(0),char(13),char(0),char(38),char(1),
-char(82),char(0),char(33),char(1),char(4),char(0),char(44),char(1),char(7),char(0),char(45),char(1),char(86),char(0),char(7),char(0),char(13),char(0),char(46),char(1),
-char(82),char(0),char(33),char(1),char(4),char(0),char(47),char(1),char(7),char(0),char(48),char(1),char(7),char(0),char(49),char(1),char(7),char(0),char(50),char(1),
-char(4),char(0),char(53),char(0),char(87),char(0),char(6),char(0),char(17),char(0),char(51),char(1),char(13),char(0),char(49),char(1),char(13),char(0),char(52),char(1),
-char(62),char(0),char(53),char(1),char(4),char(0),char(54),char(1),char(7),char(0),char(50),char(1),char(88),char(0),char(26),char(0),char(4),char(0),char(55),char(1),
-char(7),char(0),char(56),char(1),char(7),char(0),char(-90),char(0),char(7),char(0),char(57),char(1),char(7),char(0),char(58),char(1),char(7),char(0),char(59),char(1),
-char(7),char(0),char(60),char(1),char(7),char(0),char(61),char(1),char(7),char(0),char(62),char(1),char(7),char(0),char(63),char(1),char(7),char(0),char(64),char(1),
-char(7),char(0),char(65),char(1),char(7),char(0),char(66),char(1),char(7),char(0),char(67),char(1),char(7),char(0),char(68),char(1),char(7),char(0),char(69),char(1),
-char(7),char(0),char(70),char(1),char(7),char(0),char(71),char(1),char(7),char(0),char(72),char(1),char(7),char(0),char(73),char(1),char(7),char(0),char(74),char(1),
-char(4),char(0),char(75),char(1),char(4),char(0),char(76),char(1),char(4),char(0),char(77),char(1),char(4),char(0),char(78),char(1),char(4),char(0),char(-100),char(0),
-char(89),char(0),char(12),char(0),char(17),char(0),char(79),char(1),char(17),char(0),char(80),char(1),char(17),char(0),char(81),char(1),char(13),char(0),char(82),char(1),
-char(13),char(0),char(83),char(1),char(7),char(0),char(84),char(1),char(4),char(0),char(85),char(1),char(4),char(0),char(86),char(1),char(4),char(0),char(87),char(1),
-char(4),char(0),char(88),char(1),char(7),char(0),char(48),char(1),char(4),char(0),char(53),char(0),char(90),char(0),char(27),char(0),char(19),char(0),char(89),char(1),
-char(17),char(0),char(90),char(1),char(17),char(0),char(91),char(1),char(13),char(0),char(82),char(1),char(13),char(0),char(92),char(1),char(13),char(0),char(93),char(1),
-char(13),char(0),char(94),char(1),char(13),char(0),char(95),char(1),char(13),char(0),char(96),char(1),char(4),char(0),char(97),char(1),char(7),char(0),char(98),char(1),
-char(4),char(0),char(99),char(1),char(4),char(0),char(100),char(1),char(4),char(0),char(101),char(1),char(7),char(0),char(102),char(1),char(7),char(0),char(103),char(1),
-char(4),char(0),char(104),char(1),char(4),char(0),char(105),char(1),char(7),char(0),char(106),char(1),char(7),char(0),char(107),char(1),char(7),char(0),char(108),char(1),
-char(7),char(0),char(109),char(1),char(7),char(0),char(110),char(1),char(7),char(0),char(111),char(1),char(4),char(0),char(112),char(1),char(4),char(0),char(113),char(1),
-char(4),char(0),char(114),char(1),char(91),char(0),char(12),char(0),char(9),char(0),char(115),char(1),char(9),char(0),char(116),char(1),char(13),char(0),char(117),char(1),
-char(7),char(0),char(118),char(1),char(7),char(0),char(-86),char(0),char(7),char(0),char(119),char(1),char(4),char(0),char(120),char(1),char(13),char(0),char(121),char(1),
-char(4),char(0),char(122),char(1),char(4),char(0),char(123),char(1),char(4),char(0),char(124),char(1),char(4),char(0),char(53),char(0),char(92),char(0),char(19),char(0),
-char(50),char(0),char(-70),char(0),char(89),char(0),char(125),char(1),char(82),char(0),char(126),char(1),char(83),char(0),char(127),char(1),char(84),char(0),char(-128),char(1),
-char(85),char(0),char(-127),char(1),char(86),char(0),char(-126),char(1),char(87),char(0),char(-125),char(1),char(90),char(0),char(-124),char(1),char(91),char(0),char(-123),char(1),
-char(4),char(0),char(-122),char(1),char(4),char(0),char(100),char(1),char(4),char(0),char(-121),char(1),char(4),char(0),char(-120),char(1),char(4),char(0),char(-119),char(1),
-char(4),char(0),char(-118),char(1),char(4),char(0),char(-117),char(1),char(4),char(0),char(-116),char(1),char(88),char(0),char(-115),char(1),char(93),char(0),char(28),char(0),
-char(16),char(0),char(-114),char(1),char(14),char(0),char(-113),char(1),char(14),char(0),char(-112),char(1),char(14),char(0),char(-111),char(1),char(14),char(0),char(-110),char(1),
-char(14),char(0),char(-109),char(1),char(14),char(0),char(-108),char(1),char(14),char(0),char(-107),char(1),char(14),char(0),char(-106),char(1),char(14),char(0),char(-105),char(1),
-char(8),char(0),char(-104),char(1),char(4),char(0),char(-103),char(1),char(4),char(0),char(124),char(1),char(4),char(0),char(-102),char(1),char(4),char(0),char(-101),char(1),
-char(8),char(0),char(-100),char(1),char(8),char(0),char(-99),char(1),char(8),char(0),char(-98),char(1),char(8),char(0),char(-97),char(1),char(8),char(0),char(-96),char(1),
-char(8),char(0),char(-95),char(1),char(8),char(0),char(-94),char(1),char(8),char(0),char(-93),char(1),char(8),char(0),char(-92),char(1),char(0),char(0),char(-91),char(1),
-char(0),char(0),char(-90),char(1),char(48),char(0),char(-89),char(1),char(0),char(0),char(-88),char(1),char(94),char(0),char(28),char(0),char(15),char(0),char(-114),char(1),
-char(13),char(0),char(-113),char(1),char(13),char(0),char(-112),char(1),char(13),char(0),char(-111),char(1),char(13),char(0),char(-110),char(1),char(13),char(0),char(-109),char(1),
-char(13),char(0),char(-108),char(1),char(13),char(0),char(-107),char(1),char(13),char(0),char(-106),char(1),char(13),char(0),char(-105),char(1),char(4),char(0),char(-102),char(1),
-char(7),char(0),char(-104),char(1),char(4),char(0),char(-103),char(1),char(4),char(0),char(124),char(1),char(7),char(0),char(-100),char(1),char(7),char(0),char(-99),char(1),
-char(7),char(0),char(-98),char(1),char(4),char(0),char(-101),char(1),char(7),char(0),char(-97),char(1),char(7),char(0),char(-96),char(1),char(7),char(0),char(-95),char(1),
-char(7),char(0),char(-94),char(1),char(7),char(0),char(-93),char(1),char(7),char(0),char(-92),char(1),char(0),char(0),char(-91),char(1),char(0),char(0),char(-90),char(1),
-char(50),char(0),char(-89),char(1),char(0),char(0),char(-88),char(1),char(95),char(0),char(11),char(0),char(14),char(0),char(-87),char(1),char(16),char(0),char(-86),char(1),
-char(14),char(0),char(-85),char(1),char(14),char(0),char(-84),char(1),char(14),char(0),char(-83),char(1),char(8),char(0),char(-82),char(1),char(4),char(0),char(-121),char(1),
-char(0),char(0),char(37),char(0),char(0),char(0),char(-81),char(1),char(93),char(0),char(-128),char(1),char(48),char(0),char(-80),char(1),char(96),char(0),char(10),char(0),
-char(13),char(0),char(-87),char(1),char(15),char(0),char(-86),char(1),char(13),char(0),char(-85),char(1),char(13),char(0),char(-84),char(1),char(13),char(0),char(-83),char(1),
-char(7),char(0),char(-82),char(1),char(4),char(0),char(-121),char(1),char(0),char(0),char(-81),char(1),char(94),char(0),char(-128),char(1),char(50),char(0),char(-80),char(1),
-char(97),char(0),char(4),char(0),char(50),char(0),char(-79),char(1),char(96),char(0),char(-78),char(1),char(4),char(0),char(-77),char(1),char(0),char(0),char(37),char(0),
-char(98),char(0),char(4),char(0),char(48),char(0),char(-79),char(1),char(95),char(0),char(-78),char(1),char(4),char(0),char(-77),char(1),char(0),char(0),char(37),char(0),
-};
+char(7),char(0),char(-81),char(0),char(7),char(0),char(-80),char(0),char(7),char(0),char(-79),char(0),char(7),char(0),char(-78),char(0),char(7),char(0),char(-77),char(0),
+char(7),char(0),char(-76),char(0),char(4),char(0),char(-75),char(0),char(4),char(0),char(-74),char(0),char(4),char(0),char(-73),char(0),char(4),char(0),char(-72),char(0),
+char(4),char(0),char(-71),char(0),char(55),char(0),char(2),char(0),char(53),char(0),char(-70),char(0),char(14),char(0),char(-69),char(0),char(56),char(0),char(2),char(0),
+char(54),char(0),char(-70),char(0),char(13),char(0),char(-69),char(0),char(57),char(0),char(21),char(0),char(50),char(0),char(-68),char(0),char(17),char(0),char(-67),char(0),
+char(13),char(0),char(-66),char(0),char(13),char(0),char(-65),char(0),char(13),char(0),char(-64),char(0),char(13),char(0),char(-63),char(0),char(13),char(0),char(-69),char(0),
+char(13),char(0),char(-62),char(0),char(13),char(0),char(-61),char(0),char(13),char(0),char(-60),char(0),char(13),char(0),char(-59),char(0),char(7),char(0),char(-58),char(0),
+char(7),char(0),char(-57),char(0),char(7),char(0),char(-56),char(0),char(7),char(0),char(-55),char(0),char(7),char(0),char(-54),char(0),char(7),char(0),char(-53),char(0),
+char(7),char(0),char(-52),char(0),char(7),char(0),char(-51),char(0),char(7),char(0),char(-50),char(0),char(4),char(0),char(-49),char(0),char(58),char(0),char(22),char(0),
+char(48),char(0),char(-68),char(0),char(18),char(0),char(-67),char(0),char(14),char(0),char(-66),char(0),char(14),char(0),char(-65),char(0),char(14),char(0),char(-64),char(0),
+char(14),char(0),char(-63),char(0),char(14),char(0),char(-69),char(0),char(14),char(0),char(-62),char(0),char(14),char(0),char(-61),char(0),char(14),char(0),char(-60),char(0),
+char(14),char(0),char(-59),char(0),char(8),char(0),char(-58),char(0),char(8),char(0),char(-57),char(0),char(8),char(0),char(-56),char(0),char(8),char(0),char(-55),char(0),
+char(8),char(0),char(-54),char(0),char(8),char(0),char(-53),char(0),char(8),char(0),char(-52),char(0),char(8),char(0),char(-51),char(0),char(8),char(0),char(-50),char(0),
+char(4),char(0),char(-49),char(0),char(0),char(0),char(37),char(0),char(59),char(0),char(2),char(0),char(4),char(0),char(-48),char(0),char(4),char(0),char(-47),char(0),
+char(60),char(0),char(13),char(0),char(57),char(0),char(-46),char(0),char(57),char(0),char(-45),char(0),char(0),char(0),char(35),char(0),char(4),char(0),char(-127),char(0),
+char(4),char(0),char(-44),char(0),char(4),char(0),char(-43),char(0),char(4),char(0),char(-42),char(0),char(7),char(0),char(-41),char(0),char(7),char(0),char(-40),char(0),
+char(4),char(0),char(-39),char(0),char(4),char(0),char(-38),char(0),char(7),char(0),char(-37),char(0),char(4),char(0),char(-36),char(0),char(61),char(0),char(13),char(0),
+char(62),char(0),char(-46),char(0),char(62),char(0),char(-45),char(0),char(0),char(0),char(35),char(0),char(4),char(0),char(-127),char(0),char(4),char(0),char(-44),char(0),
+char(4),char(0),char(-43),char(0),char(4),char(0),char(-42),char(0),char(7),char(0),char(-41),char(0),char(7),char(0),char(-40),char(0),char(4),char(0),char(-39),char(0),
+char(4),char(0),char(-38),char(0),char(7),char(0),char(-37),char(0),char(4),char(0),char(-36),char(0),char(63),char(0),char(14),char(0),char(58),char(0),char(-46),char(0),
+char(58),char(0),char(-45),char(0),char(0),char(0),char(35),char(0),char(4),char(0),char(-127),char(0),char(4),char(0),char(-44),char(0),char(4),char(0),char(-43),char(0),
+char(4),char(0),char(-42),char(0),char(8),char(0),char(-41),char(0),char(8),char(0),char(-40),char(0),char(4),char(0),char(-39),char(0),char(4),char(0),char(-38),char(0),
+char(8),char(0),char(-37),char(0),char(4),char(0),char(-36),char(0),char(0),char(0),char(-35),char(0),char(64),char(0),char(3),char(0),char(61),char(0),char(-34),char(0),
+char(13),char(0),char(-33),char(0),char(13),char(0),char(-32),char(0),char(65),char(0),char(3),char(0),char(63),char(0),char(-34),char(0),char(14),char(0),char(-33),char(0),
+char(14),char(0),char(-32),char(0),char(66),char(0),char(3),char(0),char(61),char(0),char(-34),char(0),char(14),char(0),char(-33),char(0),char(14),char(0),char(-32),char(0),
+char(67),char(0),char(13),char(0),char(61),char(0),char(-34),char(0),char(20),char(0),char(-31),char(0),char(20),char(0),char(-30),char(0),char(4),char(0),char(-29),char(0),
+char(4),char(0),char(-28),char(0),char(4),char(0),char(-27),char(0),char(7),char(0),char(-26),char(0),char(7),char(0),char(-25),char(0),char(7),char(0),char(-24),char(0),
+char(7),char(0),char(-23),char(0),char(7),char(0),char(-22),char(0),char(7),char(0),char(-21),char(0),char(7),char(0),char(-20),char(0),char(68),char(0),char(13),char(0),
+char(61),char(0),char(-34),char(0),char(19),char(0),char(-31),char(0),char(19),char(0),char(-30),char(0),char(4),char(0),char(-29),char(0),char(4),char(0),char(-28),char(0),
+char(4),char(0),char(-27),char(0),char(7),char(0),char(-26),char(0),char(7),char(0),char(-25),char(0),char(7),char(0),char(-24),char(0),char(7),char(0),char(-23),char(0),
+char(7),char(0),char(-22),char(0),char(7),char(0),char(-21),char(0),char(7),char(0),char(-20),char(0),char(69),char(0),char(14),char(0),char(63),char(0),char(-34),char(0),
+char(20),char(0),char(-31),char(0),char(20),char(0),char(-30),char(0),char(4),char(0),char(-29),char(0),char(4),char(0),char(-28),char(0),char(4),char(0),char(-27),char(0),
+char(8),char(0),char(-26),char(0),char(8),char(0),char(-25),char(0),char(8),char(0),char(-24),char(0),char(8),char(0),char(-23),char(0),char(8),char(0),char(-22),char(0),
+char(8),char(0),char(-21),char(0),char(8),char(0),char(-20),char(0),char(0),char(0),char(-19),char(0),char(70),char(0),char(10),char(0),char(63),char(0),char(-34),char(0),
+char(20),char(0),char(-31),char(0),char(20),char(0),char(-30),char(0),char(8),char(0),char(-18),char(0),char(8),char(0),char(-17),char(0),char(8),char(0),char(-16),char(0),
+char(8),char(0),char(-22),char(0),char(8),char(0),char(-21),char(0),char(8),char(0),char(-20),char(0),char(8),char(0),char(-89),char(0),char(71),char(0),char(11),char(0),
+char(61),char(0),char(-34),char(0),char(19),char(0),char(-31),char(0),char(19),char(0),char(-30),char(0),char(7),char(0),char(-18),char(0),char(7),char(0),char(-17),char(0),
+char(7),char(0),char(-16),char(0),char(7),char(0),char(-22),char(0),char(7),char(0),char(-21),char(0),char(7),char(0),char(-20),char(0),char(7),char(0),char(-89),char(0),
+char(0),char(0),char(21),char(0),char(72),char(0),char(9),char(0),char(61),char(0),char(-34),char(0),char(19),char(0),char(-31),char(0),char(19),char(0),char(-30),char(0),
+char(13),char(0),char(-15),char(0),char(13),char(0),char(-14),char(0),char(13),char(0),char(-13),char(0),char(13),char(0),char(-12),char(0),char(4),char(0),char(-11),char(0),
+char(4),char(0),char(-10),char(0),char(73),char(0),char(9),char(0),char(63),char(0),char(-34),char(0),char(20),char(0),char(-31),char(0),char(20),char(0),char(-30),char(0),
+char(14),char(0),char(-15),char(0),char(14),char(0),char(-14),char(0),char(14),char(0),char(-13),char(0),char(14),char(0),char(-12),char(0),char(4),char(0),char(-11),char(0),
+char(4),char(0),char(-10),char(0),char(74),char(0),char(5),char(0),char(72),char(0),char(-9),char(0),char(4),char(0),char(-8),char(0),char(7),char(0),char(-7),char(0),
+char(7),char(0),char(-6),char(0),char(7),char(0),char(-5),char(0),char(75),char(0),char(5),char(0),char(73),char(0),char(-9),char(0),char(4),char(0),char(-8),char(0),
+char(8),char(0),char(-7),char(0),char(8),char(0),char(-6),char(0),char(8),char(0),char(-5),char(0),char(76),char(0),char(41),char(0),char(61),char(0),char(-34),char(0),
+char(19),char(0),char(-31),char(0),char(19),char(0),char(-30),char(0),char(13),char(0),char(-15),char(0),char(13),char(0),char(-14),char(0),char(13),char(0),char(-4),char(0),
+char(13),char(0),char(-3),char(0),char(13),char(0),char(-2),char(0),char(13),char(0),char(-1),char(0),char(13),char(0),char(0),char(1),char(13),char(0),char(1),char(1),
+char(13),char(0),char(2),char(1),char(13),char(0),char(3),char(1),char(13),char(0),char(4),char(1),char(13),char(0),char(5),char(1),char(13),char(0),char(6),char(1),
+char(0),char(0),char(7),char(1),char(0),char(0),char(8),char(1),char(0),char(0),char(9),char(1),char(0),char(0),char(10),char(1),char(0),char(0),char(11),char(1),
+char(0),char(0),char(-19),char(0),char(13),char(0),char(-13),char(0),char(13),char(0),char(-12),char(0),char(13),char(0),char(12),char(1),char(13),char(0),char(13),char(1),
+char(13),char(0),char(14),char(1),char(13),char(0),char(15),char(1),char(13),char(0),char(16),char(1),char(13),char(0),char(17),char(1),char(13),char(0),char(18),char(1),
+char(13),char(0),char(19),char(1),char(13),char(0),char(20),char(1),char(13),char(0),char(21),char(1),char(13),char(0),char(22),char(1),char(0),char(0),char(23),char(1),
+char(0),char(0),char(24),char(1),char(0),char(0),char(25),char(1),char(0),char(0),char(26),char(1),char(0),char(0),char(27),char(1),char(4),char(0),char(28),char(1),
+char(77),char(0),char(41),char(0),char(63),char(0),char(-34),char(0),char(20),char(0),char(-31),char(0),char(20),char(0),char(-30),char(0),char(14),char(0),char(-15),char(0),
+char(14),char(0),char(-14),char(0),char(14),char(0),char(-4),char(0),char(14),char(0),char(-3),char(0),char(14),char(0),char(-2),char(0),char(14),char(0),char(-1),char(0),
+char(14),char(0),char(0),char(1),char(14),char(0),char(1),char(1),char(14),char(0),char(2),char(1),char(14),char(0),char(3),char(1),char(14),char(0),char(4),char(1),
+char(14),char(0),char(5),char(1),char(14),char(0),char(6),char(1),char(0),char(0),char(7),char(1),char(0),char(0),char(8),char(1),char(0),char(0),char(9),char(1),
+char(0),char(0),char(10),char(1),char(0),char(0),char(11),char(1),char(0),char(0),char(-19),char(0),char(14),char(0),char(-13),char(0),char(14),char(0),char(-12),char(0),
+char(14),char(0),char(12),char(1),char(14),char(0),char(13),char(1),char(14),char(0),char(14),char(1),char(14),char(0),char(15),char(1),char(14),char(0),char(16),char(1),
+char(14),char(0),char(17),char(1),char(14),char(0),char(18),char(1),char(14),char(0),char(19),char(1),char(14),char(0),char(20),char(1),char(14),char(0),char(21),char(1),
+char(14),char(0),char(22),char(1),char(0),char(0),char(23),char(1),char(0),char(0),char(24),char(1),char(0),char(0),char(25),char(1),char(0),char(0),char(26),char(1),
+char(0),char(0),char(27),char(1),char(4),char(0),char(28),char(1),char(78),char(0),char(9),char(0),char(61),char(0),char(-34),char(0),char(19),char(0),char(-31),char(0),
+char(19),char(0),char(-30),char(0),char(7),char(0),char(-15),char(0),char(7),char(0),char(-14),char(0),char(7),char(0),char(-13),char(0),char(7),char(0),char(-12),char(0),
+char(4),char(0),char(-11),char(0),char(4),char(0),char(-10),char(0),char(79),char(0),char(9),char(0),char(63),char(0),char(-34),char(0),char(20),char(0),char(-31),char(0),
+char(20),char(0),char(-30),char(0),char(8),char(0),char(-15),char(0),char(8),char(0),char(-14),char(0),char(8),char(0),char(-13),char(0),char(8),char(0),char(-12),char(0),
+char(4),char(0),char(-11),char(0),char(4),char(0),char(-10),char(0),char(80),char(0),char(5),char(0),char(60),char(0),char(-34),char(0),char(13),char(0),char(29),char(1),
+char(13),char(0),char(30),char(1),char(7),char(0),char(31),char(1),char(0),char(0),char(37),char(0),char(81),char(0),char(4),char(0),char(63),char(0),char(-34),char(0),
+char(14),char(0),char(29),char(1),char(14),char(0),char(30),char(1),char(8),char(0),char(31),char(1),char(82),char(0),char(4),char(0),char(7),char(0),char(32),char(1),
+char(7),char(0),char(33),char(1),char(7),char(0),char(34),char(1),char(4),char(0),char(79),char(0),char(83),char(0),char(10),char(0),char(82),char(0),char(35),char(1),
+char(13),char(0),char(36),char(1),char(13),char(0),char(37),char(1),char(13),char(0),char(38),char(1),char(13),char(0),char(39),char(1),char(13),char(0),char(40),char(1),
+char(7),char(0),char(-58),char(0),char(7),char(0),char(41),char(1),char(4),char(0),char(42),char(1),char(4),char(0),char(53),char(0),char(84),char(0),char(4),char(0),
+char(82),char(0),char(35),char(1),char(4),char(0),char(43),char(1),char(7),char(0),char(44),char(1),char(4),char(0),char(45),char(1),char(85),char(0),char(4),char(0),
+char(13),char(0),char(40),char(1),char(82),char(0),char(35),char(1),char(4),char(0),char(46),char(1),char(7),char(0),char(47),char(1),char(86),char(0),char(7),char(0),
+char(13),char(0),char(48),char(1),char(82),char(0),char(35),char(1),char(4),char(0),char(49),char(1),char(7),char(0),char(50),char(1),char(7),char(0),char(51),char(1),
+char(7),char(0),char(52),char(1),char(4),char(0),char(53),char(0),char(87),char(0),char(6),char(0),char(17),char(0),char(53),char(1),char(13),char(0),char(51),char(1),
+char(13),char(0),char(54),char(1),char(62),char(0),char(55),char(1),char(4),char(0),char(56),char(1),char(7),char(0),char(52),char(1),char(88),char(0),char(26),char(0),
+char(4),char(0),char(57),char(1),char(7),char(0),char(58),char(1),char(7),char(0),char(-89),char(0),char(7),char(0),char(59),char(1),char(7),char(0),char(60),char(1),
+char(7),char(0),char(61),char(1),char(7),char(0),char(62),char(1),char(7),char(0),char(63),char(1),char(7),char(0),char(64),char(1),char(7),char(0),char(65),char(1),
+char(7),char(0),char(66),char(1),char(7),char(0),char(67),char(1),char(7),char(0),char(68),char(1),char(7),char(0),char(69),char(1),char(7),char(0),char(70),char(1),
+char(7),char(0),char(71),char(1),char(7),char(0),char(72),char(1),char(7),char(0),char(73),char(1),char(7),char(0),char(74),char(1),char(7),char(0),char(75),char(1),
+char(7),char(0),char(76),char(1),char(4),char(0),char(77),char(1),char(4),char(0),char(78),char(1),char(4),char(0),char(79),char(1),char(4),char(0),char(80),char(1),
+char(4),char(0),char(-99),char(0),char(89),char(0),char(12),char(0),char(17),char(0),char(81),char(1),char(17),char(0),char(82),char(1),char(17),char(0),char(83),char(1),
+char(13),char(0),char(84),char(1),char(13),char(0),char(85),char(1),char(7),char(0),char(86),char(1),char(4),char(0),char(87),char(1),char(4),char(0),char(88),char(1),
+char(4),char(0),char(89),char(1),char(4),char(0),char(90),char(1),char(7),char(0),char(50),char(1),char(4),char(0),char(53),char(0),char(90),char(0),char(27),char(0),
+char(19),char(0),char(91),char(1),char(17),char(0),char(92),char(1),char(17),char(0),char(93),char(1),char(13),char(0),char(84),char(1),char(13),char(0),char(94),char(1),
+char(13),char(0),char(95),char(1),char(13),char(0),char(96),char(1),char(13),char(0),char(97),char(1),char(13),char(0),char(98),char(1),char(4),char(0),char(99),char(1),
+char(7),char(0),char(100),char(1),char(4),char(0),char(101),char(1),char(4),char(0),char(102),char(1),char(4),char(0),char(103),char(1),char(7),char(0),char(104),char(1),
+char(7),char(0),char(105),char(1),char(4),char(0),char(106),char(1),char(4),char(0),char(107),char(1),char(7),char(0),char(108),char(1),char(7),char(0),char(109),char(1),
+char(7),char(0),char(110),char(1),char(7),char(0),char(111),char(1),char(7),char(0),char(112),char(1),char(7),char(0),char(113),char(1),char(4),char(0),char(114),char(1),
+char(4),char(0),char(115),char(1),char(4),char(0),char(116),char(1),char(91),char(0),char(12),char(0),char(9),char(0),char(117),char(1),char(9),char(0),char(118),char(1),
+char(13),char(0),char(119),char(1),char(7),char(0),char(120),char(1),char(7),char(0),char(-85),char(0),char(7),char(0),char(121),char(1),char(4),char(0),char(122),char(1),
+char(13),char(0),char(123),char(1),char(4),char(0),char(124),char(1),char(4),char(0),char(125),char(1),char(4),char(0),char(126),char(1),char(4),char(0),char(53),char(0),
+char(92),char(0),char(19),char(0),char(50),char(0),char(-68),char(0),char(89),char(0),char(127),char(1),char(82),char(0),char(-128),char(1),char(83),char(0),char(-127),char(1),
+char(84),char(0),char(-126),char(1),char(85),char(0),char(-125),char(1),char(86),char(0),char(-124),char(1),char(87),char(0),char(-123),char(1),char(90),char(0),char(-122),char(1),
+char(91),char(0),char(-121),char(1),char(4),char(0),char(-120),char(1),char(4),char(0),char(102),char(1),char(4),char(0),char(-119),char(1),char(4),char(0),char(-118),char(1),
+char(4),char(0),char(-117),char(1),char(4),char(0),char(-116),char(1),char(4),char(0),char(-115),char(1),char(4),char(0),char(-114),char(1),char(88),char(0),char(-113),char(1),
+char(93),char(0),char(28),char(0),char(16),char(0),char(-112),char(1),char(14),char(0),char(-111),char(1),char(14),char(0),char(-110),char(1),char(14),char(0),char(-109),char(1),
+char(14),char(0),char(-108),char(1),char(14),char(0),char(-107),char(1),char(14),char(0),char(-106),char(1),char(14),char(0),char(-105),char(1),char(14),char(0),char(-104),char(1),
+char(14),char(0),char(-103),char(1),char(8),char(0),char(-102),char(1),char(4),char(0),char(-101),char(1),char(4),char(0),char(126),char(1),char(4),char(0),char(-100),char(1),
+char(4),char(0),char(-99),char(1),char(8),char(0),char(-98),char(1),char(8),char(0),char(-97),char(1),char(8),char(0),char(-96),char(1),char(8),char(0),char(-95),char(1),
+char(8),char(0),char(-94),char(1),char(8),char(0),char(-93),char(1),char(8),char(0),char(-92),char(1),char(8),char(0),char(-91),char(1),char(8),char(0),char(-90),char(1),
+char(0),char(0),char(-89),char(1),char(0),char(0),char(-88),char(1),char(48),char(0),char(-87),char(1),char(0),char(0),char(-86),char(1),char(94),char(0),char(28),char(0),
+char(15),char(0),char(-112),char(1),char(13),char(0),char(-111),char(1),char(13),char(0),char(-110),char(1),char(13),char(0),char(-109),char(1),char(13),char(0),char(-108),char(1),
+char(13),char(0),char(-107),char(1),char(13),char(0),char(-106),char(1),char(13),char(0),char(-105),char(1),char(13),char(0),char(-104),char(1),char(13),char(0),char(-103),char(1),
+char(4),char(0),char(-100),char(1),char(7),char(0),char(-102),char(1),char(4),char(0),char(-101),char(1),char(4),char(0),char(126),char(1),char(7),char(0),char(-98),char(1),
+char(7),char(0),char(-97),char(1),char(7),char(0),char(-96),char(1),char(4),char(0),char(-99),char(1),char(7),char(0),char(-95),char(1),char(7),char(0),char(-94),char(1),
+char(7),char(0),char(-93),char(1),char(7),char(0),char(-92),char(1),char(7),char(0),char(-91),char(1),char(7),char(0),char(-90),char(1),char(0),char(0),char(-89),char(1),
+char(0),char(0),char(-88),char(1),char(50),char(0),char(-87),char(1),char(0),char(0),char(-86),char(1),char(95),char(0),char(11),char(0),char(14),char(0),char(-85),char(1),
+char(16),char(0),char(-84),char(1),char(14),char(0),char(-83),char(1),char(14),char(0),char(-82),char(1),char(14),char(0),char(-81),char(1),char(8),char(0),char(-80),char(1),
+char(4),char(0),char(-119),char(1),char(0),char(0),char(37),char(0),char(0),char(0),char(-79),char(1),char(93),char(0),char(-126),char(1),char(48),char(0),char(-78),char(1),
+char(96),char(0),char(10),char(0),char(13),char(0),char(-85),char(1),char(15),char(0),char(-84),char(1),char(13),char(0),char(-83),char(1),char(13),char(0),char(-82),char(1),
+char(13),char(0),char(-81),char(1),char(7),char(0),char(-80),char(1),char(4),char(0),char(-119),char(1),char(0),char(0),char(-79),char(1),char(94),char(0),char(-126),char(1),
+char(50),char(0),char(-78),char(1),char(97),char(0),char(4),char(0),char(50),char(0),char(-77),char(1),char(96),char(0),char(-76),char(1),char(4),char(0),char(-75),char(1),
+char(0),char(0),char(37),char(0),char(98),char(0),char(4),char(0),char(48),char(0),char(-77),char(1),char(95),char(0),char(-76),char(1),char(4),char(0),char(-75),char(1),
+char(0),char(0),char(37),char(0),};
int sBulletDNAlen= sizeof(sBulletDNAstr);
-
-// clang-format on
diff --git a/thirdparty/bullet/LinearMath/btSerializer.h b/thirdparty/bullet/LinearMath/btSerializer.h
index ba34441615..2ee712047f 100644
--- a/thirdparty/bullet/LinearMath/btSerializer.h
+++ b/thirdparty/bullet/LinearMath/btSerializer.h
@@ -481,7 +481,7 @@ public:
buffer[9] = '2';
buffer[10] = '8';
- buffer[11] = '8';
+ buffer[11] = '9';
}
virtual void startSerialization()
diff --git a/thirdparty/bullet/LinearMath/btSerializer64.cpp b/thirdparty/bullet/LinearMath/btSerializer64.cpp
index cf281cdb36..6c4bc7031f 100644
--- a/thirdparty/bullet/LinearMath/btSerializer64.cpp
+++ b/thirdparty/bullet/LinearMath/btSerializer64.cpp
@@ -1,6 +1,5 @@
-// clang-format off
char sBulletDNAstr64[]= {
-char(83),char(68),char(78),char(65),char(78),char(65),char(77),char(69),char(-76),char(1),char(0),char(0),char(109),char(95),char(115),char(105),char(122),char(101),char(0),char(109),
+char(83),char(68),char(78),char(65),char(78),char(65),char(77),char(69),char(-74),char(1),char(0),char(0),char(109),char(95),char(115),char(105),char(122),char(101),char(0),char(109),
char(95),char(99),char(97),char(112),char(97),char(99),char(105),char(116),char(121),char(0),char(42),char(109),char(95),char(100),char(97),char(116),char(97),char(0),char(109),char(95),
char(99),char(111),char(108),char(108),char(105),char(115),char(105),char(111),char(110),char(83),char(104),char(97),char(112),char(101),char(115),char(0),char(109),char(95),char(99),char(111),
char(108),char(108),char(105),char(115),char(105),char(111),char(110),char(79),char(98),char(106),char(101),char(99),char(116),char(115),char(0),char(109),char(95),char(99),char(111),char(110),
@@ -87,605 +86,607 @@ char(101),char(76),char(97),char(116),char(101),char(114),char(97),char(108),cha
char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),char(67),char(97),char(99),char(104),char(101),char(68),char(105),char(115),char(116),
char(97),char(110),char(99),char(101),char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),char(67),char(97),char(99),char(104),char(101),
char(65),char(112),char(112),char(108),char(105),char(101),char(100),char(73),char(109),char(112),char(117),char(108),char(115),char(101),char(91),char(52),char(93),char(0),char(109),char(95),
-char(112),char(111),char(105),char(110),char(116),char(67),char(97),char(99),char(104),char(101),char(67),char(111),char(109),char(98),char(105),char(110),char(101),char(100),char(70),char(114),
-char(105),char(99),char(116),char(105),char(111),char(110),char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),char(67),char(97),char(99),
-char(104),char(101),char(67),char(111),char(109),char(98),char(105),char(110),char(101),char(100),char(82),char(111),char(108),char(108),char(105),char(110),char(103),char(70),char(114),char(105),
-char(99),char(116),char(105),char(111),char(110),char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),char(67),char(97),char(99),char(104),
-char(101),char(67),char(111),char(109),char(98),char(105),char(110),char(101),char(100),char(83),char(112),char(105),char(110),char(110),char(105),char(110),char(103),char(70),char(114),char(105),
-char(99),char(116),char(105),char(111),char(110),char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),char(67),char(97),char(99),char(104),
-char(101),char(67),char(111),char(109),char(98),char(105),char(110),char(101),char(100),char(82),char(101),char(115),char(116),char(105),char(116),char(117),char(116),char(105),char(111),char(110),
-char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),char(67),char(97),char(99),char(104),char(101),char(80),char(97),char(114),char(116),
-char(73),char(100),char(48),char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),char(67),char(97),char(99),char(104),char(101),char(80),
-char(97),char(114),char(116),char(73),char(100),char(49),char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),char(67),char(97),char(99),
-char(104),char(101),char(73),char(110),char(100),char(101),char(120),char(48),char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),char(67),
-char(97),char(99),char(104),char(101),char(73),char(110),char(100),char(101),char(120),char(49),char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),char(110),
-char(116),char(67),char(97),char(99),char(104),char(101),char(67),char(111),char(110),char(116),char(97),char(99),char(116),char(80),char(111),char(105),char(110),char(116),char(70),char(108),
-char(97),char(103),char(115),char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),char(67),char(97),char(99),char(104),char(101),char(65),
-char(112),char(112),char(108),char(105),char(101),char(100),char(73),char(109),char(112),char(117),char(108),char(115),char(101),char(76),char(97),char(116),char(101),char(114),char(97),char(108),
-char(49),char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),char(67),char(97),char(99),char(104),char(101),char(65),char(112),char(112),
-char(108),char(105),char(101),char(100),char(73),char(109),char(112),char(117),char(108),char(115),char(101),char(76),char(97),char(116),char(101),char(114),char(97),char(108),char(50),char(91),
-char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),char(67),char(97),char(99),char(104),char(101),char(67),char(111),char(110),char(116),char(97),
-char(99),char(116),char(77),char(111),char(116),char(105),char(111),char(110),char(49),char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),
-char(67),char(97),char(99),char(104),char(101),char(67),char(111),char(110),char(116),char(97),char(99),char(116),char(77),char(111),char(116),char(105),char(111),char(110),char(50),char(91),
-char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),char(67),char(97),char(99),char(104),char(101),char(67),char(111),char(110),char(116),char(97),
-char(99),char(116),char(67),char(70),char(77),char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),char(67),char(97),char(99),char(104),
-char(101),char(67),char(111),char(109),char(98),char(105),char(110),char(101),char(100),char(67),char(111),char(110),char(116),char(97),char(99),char(116),char(83),char(116),char(105),char(102),
-char(102),char(110),char(101),char(115),char(115),char(49),char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),char(67),char(97),char(99),
-char(104),char(101),char(67),char(111),char(110),char(116),char(97),char(99),char(116),char(69),char(82),char(80),char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),
-char(105),char(110),char(116),char(67),char(97),char(99),char(104),char(101),char(67),char(111),char(109),char(98),char(105),char(110),char(101),char(100),char(67),char(111),char(110),char(116),
-char(97),char(99),char(116),char(68),char(97),char(109),char(112),char(105),char(110),char(103),char(49),char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),
-char(110),char(116),char(67),char(97),char(99),char(104),char(101),char(70),char(114),char(105),char(99),char(116),char(105),char(111),char(110),char(67),char(70),char(77),char(91),char(52),
-char(93),char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),char(67),char(97),char(99),char(104),char(101),char(76),char(105),char(102),char(101),char(84),char(105),
-char(109),char(101),char(91),char(52),char(93),char(0),char(109),char(95),char(110),char(117),char(109),char(67),char(97),char(99),char(104),char(101),char(100),char(80),char(111),char(105),
-char(110),char(116),char(115),char(0),char(109),char(95),char(99),char(111),char(109),char(112),char(97),char(110),char(105),char(111),char(110),char(73),char(100),char(65),char(0),char(109),
-char(95),char(99),char(111),char(109),char(112),char(97),char(110),char(105),char(111),char(110),char(73),char(100),char(66),char(0),char(109),char(95),char(105),char(110),char(100),char(101),
-char(120),char(49),char(97),char(0),char(109),char(95),char(111),char(98),char(106),char(101),char(99),char(116),char(84),char(121),char(112),char(101),char(0),char(109),char(95),char(99),
-char(111),char(110),char(116),char(97),char(99),char(116),char(66),char(114),char(101),char(97),char(107),char(105),char(110),char(103),char(84),char(104),char(114),char(101),char(115),char(104),
-char(111),char(108),char(100),char(0),char(109),char(95),char(99),char(111),char(110),char(116),char(97),char(99),char(116),char(80),char(114),char(111),char(99),char(101),char(115),char(115),
-char(105),char(110),char(103),char(84),char(104),char(114),char(101),char(115),char(104),char(111),char(108),char(100),char(0),char(42),char(109),char(95),char(98),char(111),char(100),char(121),
-char(48),char(0),char(42),char(109),char(95),char(98),char(111),char(100),char(121),char(49),char(0),char(109),char(95),char(103),char(105),char(109),char(112),char(97),char(99),char(116),
-char(83),char(117),char(98),char(84),char(121),char(112),char(101),char(0),char(42),char(109),char(95),char(117),char(110),char(115),char(99),char(97),char(108),char(101),char(100),char(80),
-char(111),char(105),char(110),char(116),char(115),char(70),char(108),char(111),char(97),char(116),char(80),char(116),char(114),char(0),char(42),char(109),char(95),char(117),char(110),char(115),
-char(99),char(97),char(108),char(101),char(100),char(80),char(111),char(105),char(110),char(116),char(115),char(68),char(111),char(117),char(98),char(108),char(101),char(80),char(116),char(114),
-char(0),char(109),char(95),char(110),char(117),char(109),char(85),char(110),char(115),char(99),char(97),char(108),char(101),char(100),char(80),char(111),char(105),char(110),char(116),char(115),
-char(0),char(109),char(95),char(112),char(97),char(100),char(100),char(105),char(110),char(103),char(51),char(91),char(52),char(93),char(0),char(42),char(109),char(95),char(98),char(114),
-char(111),char(97),char(100),char(112),char(104),char(97),char(115),char(101),char(72),char(97),char(110),char(100),char(108),char(101),char(0),char(42),char(109),char(95),char(99),char(111),
-char(108),char(108),char(105),char(115),char(105),char(111),char(110),char(83),char(104),char(97),char(112),char(101),char(0),char(42),char(109),char(95),char(114),char(111),char(111),char(116),
-char(67),char(111),char(108),char(108),char(105),char(115),char(105),char(111),char(110),char(83),char(104),char(97),char(112),char(101),char(0),char(109),char(95),char(119),char(111),char(114),
-char(108),char(100),char(84),char(114),char(97),char(110),char(115),char(102),char(111),char(114),char(109),char(0),char(109),char(95),char(105),char(110),char(116),char(101),char(114),char(112),
-char(111),char(108),char(97),char(116),char(105),char(111),char(110),char(87),char(111),char(114),char(108),char(100),char(84),char(114),char(97),char(110),char(115),char(102),char(111),char(114),
-char(109),char(0),char(109),char(95),char(105),char(110),char(116),char(101),char(114),char(112),char(111),char(108),char(97),char(116),char(105),char(111),char(110),char(76),char(105),char(110),
-char(101),char(97),char(114),char(86),char(101),char(108),char(111),char(99),char(105),char(116),char(121),char(0),char(109),char(95),char(105),char(110),char(116),char(101),char(114),char(112),
-char(111),char(108),char(97),char(116),char(105),char(111),char(110),char(65),char(110),char(103),char(117),char(108),char(97),char(114),char(86),char(101),char(108),char(111),char(99),char(105),
-char(116),char(121),char(0),char(109),char(95),char(97),char(110),char(105),char(115),char(111),char(116),char(114),char(111),char(112),char(105),char(99),char(70),char(114),char(105),char(99),
-char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(100),char(101),char(97),char(99),char(116),char(105),char(118),char(97),char(116),char(105),char(111),char(110),char(84),
-char(105),char(109),char(101),char(0),char(109),char(95),char(102),char(114),char(105),char(99),char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(114),char(111),char(108),
-char(108),char(105),char(110),char(103),char(70),char(114),char(105),char(99),char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(99),char(111),char(110),char(116),char(97),
-char(99),char(116),char(68),char(97),char(109),char(112),char(105),char(110),char(103),char(0),char(109),char(95),char(99),char(111),char(110),char(116),char(97),char(99),char(116),char(83),
-char(116),char(105),char(102),char(102),char(110),char(101),char(115),char(115),char(0),char(109),char(95),char(114),char(101),char(115),char(116),char(105),char(116),char(117),char(116),char(105),
-char(111),char(110),char(0),char(109),char(95),char(104),char(105),char(116),char(70),char(114),char(97),char(99),char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(99),
-char(99),char(100),char(83),char(119),char(101),char(112),char(116),char(83),char(112),char(104),char(101),char(114),char(101),char(82),char(97),char(100),char(105),char(117),char(115),char(0),
-char(109),char(95),char(99),char(99),char(100),char(77),char(111),char(116),char(105),char(111),char(110),char(84),char(104),char(114),char(101),char(115),char(104),char(111),char(108),char(100),
-char(0),char(109),char(95),char(104),char(97),char(115),char(65),char(110),char(105),char(115),char(111),char(116),char(114),char(111),char(112),char(105),char(99),char(70),char(114),char(105),
-char(99),char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(99),char(111),char(108),char(108),char(105),char(115),char(105),char(111),char(110),char(70),char(108),char(97),
-char(103),char(115),char(0),char(109),char(95),char(105),char(115),char(108),char(97),char(110),char(100),char(84),char(97),char(103),char(49),char(0),char(109),char(95),char(99),char(111),
-char(109),char(112),char(97),char(110),char(105),char(111),char(110),char(73),char(100),char(0),char(109),char(95),char(97),char(99),char(116),char(105),char(118),char(97),char(116),char(105),
-char(111),char(110),char(83),char(116),char(97),char(116),char(101),char(49),char(0),char(109),char(95),char(105),char(110),char(116),char(101),char(114),char(110),char(97),char(108),char(84),
-char(121),char(112),char(101),char(0),char(109),char(95),char(99),char(104),char(101),char(99),char(107),char(67),char(111),char(108),char(108),char(105),char(100),char(101),char(87),char(105),
-char(116),char(104),char(0),char(109),char(95),char(99),char(111),char(108),char(108),char(105),char(115),char(105),char(111),char(110),char(70),char(105),char(108),char(116),char(101),char(114),
-char(71),char(114),char(111),char(117),char(112),char(0),char(109),char(95),char(99),char(111),char(108),char(108),char(105),char(115),char(105),char(111),char(110),char(70),char(105),char(108),
-char(116),char(101),char(114),char(77),char(97),char(115),char(107),char(0),char(109),char(95),char(117),char(110),char(105),char(113),char(117),char(101),char(73),char(100),char(0),char(109),
-char(95),char(116),char(97),char(117),char(0),char(109),char(95),char(100),char(97),char(109),char(112),char(105),char(110),char(103),char(0),char(109),char(95),char(116),char(105),char(109),
-char(101),char(83),char(116),char(101),char(112),char(0),char(109),char(95),char(109),char(97),char(120),char(69),char(114),char(114),char(111),char(114),char(82),char(101),char(100),char(117),
-char(99),char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(115),char(111),char(114),char(0),char(109),char(95),char(101),char(114),char(112),char(0),char(109),char(95),
-char(101),char(114),char(112),char(50),char(0),char(109),char(95),char(103),char(108),char(111),char(98),char(97),char(108),char(67),char(102),char(109),char(0),char(109),char(95),char(115),
-char(112),char(108),char(105),char(116),char(73),char(109),char(112),char(117),char(108),char(115),char(101),char(80),char(101),char(110),char(101),char(116),char(114),char(97),char(116),char(105),
-char(111),char(110),char(84),char(104),char(114),char(101),char(115),char(104),char(111),char(108),char(100),char(0),char(109),char(95),char(115),char(112),char(108),char(105),char(116),char(73),
-char(109),char(112),char(117),char(108),char(115),char(101),char(84),char(117),char(114),char(110),char(69),char(114),char(112),char(0),char(109),char(95),char(108),char(105),char(110),char(101),
-char(97),char(114),char(83),char(108),char(111),char(112),char(0),char(109),char(95),char(119),char(97),char(114),char(109),char(115),char(116),char(97),char(114),char(116),char(105),char(110),
-char(103),char(70),char(97),char(99),char(116),char(111),char(114),char(0),char(109),char(95),char(109),char(97),char(120),char(71),char(121),char(114),char(111),char(115),char(99),char(111),
-char(112),char(105),char(99),char(70),char(111),char(114),char(99),char(101),char(0),char(109),char(95),char(115),char(105),char(110),char(103),char(108),char(101),char(65),char(120),char(105),
-char(115),char(82),char(111),char(108),char(108),char(105),char(110),char(103),char(70),char(114),char(105),char(99),char(116),char(105),char(111),char(110),char(84),char(104),char(114),char(101),
-char(115),char(104),char(111),char(108),char(100),char(0),char(109),char(95),char(110),char(117),char(109),char(73),char(116),char(101),char(114),char(97),char(116),char(105),char(111),char(110),
-char(115),char(0),char(109),char(95),char(115),char(111),char(108),char(118),char(101),char(114),char(77),char(111),char(100),char(101),char(0),char(109),char(95),char(114),char(101),char(115),
-char(116),char(105),char(110),char(103),char(67),char(111),char(110),char(116),char(97),char(99),char(116),char(82),char(101),char(115),char(116),char(105),char(116),char(117),char(116),char(105),
-char(111),char(110),char(84),char(104),char(114),char(101),char(115),char(104),char(111),char(108),char(100),char(0),char(109),char(95),char(109),char(105),char(110),char(105),char(109),char(117),
-char(109),char(83),char(111),char(108),char(118),char(101),char(114),char(66),char(97),char(116),char(99),char(104),char(83),char(105),char(122),char(101),char(0),char(109),char(95),char(115),
-char(112),char(108),char(105),char(116),char(73),char(109),char(112),char(117),char(108),char(115),char(101),char(0),char(109),char(95),char(115),char(111),char(108),char(118),char(101),char(114),
-char(73),char(110),char(102),char(111),char(0),char(109),char(95),char(103),char(114),char(97),char(118),char(105),char(116),char(121),char(0),char(109),char(95),char(99),char(111),char(108),
-char(108),char(105),char(115),char(105),char(111),char(110),char(79),char(98),char(106),char(101),char(99),char(116),char(68),char(97),char(116),char(97),char(0),char(109),char(95),char(105),
-char(110),char(118),char(73),char(110),char(101),char(114),char(116),char(105),char(97),char(84),char(101),char(110),char(115),char(111),char(114),char(87),char(111),char(114),char(108),char(100),
-char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(86),char(101),char(108),char(111),char(99),char(105),char(116),char(121),char(0),char(109),char(95),
-char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(86),char(101),char(108),char(111),char(99),char(105),char(116),char(121),char(0),char(109),char(95),char(97),char(110),
-char(103),char(117),char(108),char(97),char(114),char(70),char(97),char(99),char(116),char(111),char(114),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),
-char(70),char(97),char(99),char(116),char(111),char(114),char(0),char(109),char(95),char(103),char(114),char(97),char(118),char(105),char(116),char(121),char(95),char(97),char(99),char(99),
-char(101),char(108),char(101),char(114),char(97),char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(105),char(110),char(118),char(73),char(110),char(101),char(114),char(116),
-char(105),char(97),char(76),char(111),char(99),char(97),char(108),char(0),char(109),char(95),char(116),char(111),char(116),char(97),char(108),char(70),char(111),char(114),char(99),char(101),
-char(0),char(109),char(95),char(116),char(111),char(116),char(97),char(108),char(84),char(111),char(114),char(113),char(117),char(101),char(0),char(109),char(95),char(105),char(110),char(118),
-char(101),char(114),char(115),char(101),char(77),char(97),char(115),char(115),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(68),char(97),char(109),
-char(112),char(105),char(110),char(103),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(68),char(97),char(109),char(112),char(105),char(110),
-char(103),char(0),char(109),char(95),char(97),char(100),char(100),char(105),char(116),char(105),char(111),char(110),char(97),char(108),char(68),char(97),char(109),char(112),char(105),char(110),
-char(103),char(70),char(97),char(99),char(116),char(111),char(114),char(0),char(109),char(95),char(97),char(100),char(100),char(105),char(116),char(105),char(111),char(110),char(97),char(108),
-char(76),char(105),char(110),char(101),char(97),char(114),char(68),char(97),char(109),char(112),char(105),char(110),char(103),char(84),char(104),char(114),char(101),char(115),char(104),char(111),
-char(108),char(100),char(83),char(113),char(114),char(0),char(109),char(95),char(97),char(100),char(100),char(105),char(116),char(105),char(111),char(110),char(97),char(108),char(65),char(110),
-char(103),char(117),char(108),char(97),char(114),char(68),char(97),char(109),char(112),char(105),char(110),char(103),char(84),char(104),char(114),char(101),char(115),char(104),char(111),char(108),
-char(100),char(83),char(113),char(114),char(0),char(109),char(95),char(97),char(100),char(100),char(105),char(116),char(105),char(111),char(110),char(97),char(108),char(65),char(110),char(103),
-char(117),char(108),char(97),char(114),char(68),char(97),char(109),char(112),char(105),char(110),char(103),char(70),char(97),char(99),char(116),char(111),char(114),char(0),char(109),char(95),
-char(108),char(105),char(110),char(101),char(97),char(114),char(83),char(108),char(101),char(101),char(112),char(105),char(110),char(103),char(84),char(104),char(114),char(101),char(115),char(104),
-char(111),char(108),char(100),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(83),char(108),char(101),char(101),char(112),char(105),char(110),
-char(103),char(84),char(104),char(114),char(101),char(115),char(104),char(111),char(108),char(100),char(0),char(109),char(95),char(97),char(100),char(100),char(105),char(116),char(105),char(111),
-char(110),char(97),char(108),char(68),char(97),char(109),char(112),char(105),char(110),char(103),char(0),char(109),char(95),char(110),char(117),char(109),char(67),char(111),char(110),char(115),
-char(116),char(114),char(97),char(105),char(110),char(116),char(82),char(111),char(119),char(115),char(0),char(110),char(117),char(98),char(0),char(42),char(109),char(95),char(114),char(98),
-char(65),char(0),char(42),char(109),char(95),char(114),char(98),char(66),char(0),char(109),char(95),char(117),char(115),char(101),char(114),char(67),char(111),char(110),char(115),char(116),
-char(114),char(97),char(105),char(110),char(116),char(84),char(121),char(112),char(101),char(0),char(109),char(95),char(117),char(115),char(101),char(114),char(67),char(111),char(110),char(115),
-char(116),char(114),char(97),char(105),char(110),char(116),char(73),char(100),char(0),char(109),char(95),char(110),char(101),char(101),char(100),char(115),char(70),char(101),char(101),char(100),
-char(98),char(97),char(99),char(107),char(0),char(109),char(95),char(97),char(112),char(112),char(108),char(105),char(101),char(100),char(73),char(109),char(112),char(117),char(108),char(115),
-char(101),char(0),char(109),char(95),char(100),char(98),char(103),char(68),char(114),char(97),char(119),char(83),char(105),char(122),char(101),char(0),char(109),char(95),char(100),char(105),
-char(115),char(97),char(98),char(108),char(101),char(67),char(111),char(108),char(108),char(105),char(115),char(105),char(111),char(110),char(115),char(66),char(101),char(116),char(119),char(101),
-char(101),char(110),char(76),char(105),char(110),char(107),char(101),char(100),char(66),char(111),char(100),char(105),char(101),char(115),char(0),char(109),char(95),char(111),char(118),char(101),
-char(114),char(114),char(105),char(100),char(101),char(78),char(117),char(109),char(83),char(111),char(108),char(118),char(101),char(114),char(73),char(116),char(101),char(114),char(97),char(116),
-char(105),char(111),char(110),char(115),char(0),char(109),char(95),char(98),char(114),char(101),char(97),char(107),char(105),char(110),char(103),char(73),char(109),char(112),char(117),char(108),
-char(115),char(101),char(84),char(104),char(114),char(101),char(115),char(104),char(111),char(108),char(100),char(0),char(109),char(95),char(105),char(115),char(69),char(110),char(97),char(98),
-char(108),char(101),char(100),char(0),char(112),char(97),char(100),char(100),char(105),char(110),char(103),char(91),char(52),char(93),char(0),char(109),char(95),char(116),char(121),char(112),
-char(101),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(68),char(97),char(116),char(97),char(0),char(109),char(95),char(112),char(105),
-char(118),char(111),char(116),char(73),char(110),char(65),char(0),char(109),char(95),char(112),char(105),char(118),char(111),char(116),char(73),char(110),char(66),char(0),char(109),char(95),
-char(114),char(98),char(65),char(70),char(114),char(97),char(109),char(101),char(0),char(109),char(95),char(114),char(98),char(66),char(70),char(114),char(97),char(109),char(101),char(0),
-char(109),char(95),char(117),char(115),char(101),char(82),char(101),char(102),char(101),char(114),char(101),char(110),char(99),char(101),char(70),char(114),char(97),char(109),char(101),char(65),
-char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(79),char(110),char(108),char(121),char(0),char(109),char(95),char(101),char(110),char(97),
-char(98),char(108),char(101),char(65),char(110),char(103),char(117),char(108),char(97),char(114),char(77),char(111),char(116),char(111),char(114),char(0),char(109),char(95),char(109),char(111),
-char(116),char(111),char(114),char(84),char(97),char(114),char(103),char(101),char(116),char(86),char(101),char(108),char(111),char(99),char(105),char(116),char(121),char(0),char(109),char(95),
-char(109),char(97),char(120),char(77),char(111),char(116),char(111),char(114),char(73),char(109),char(112),char(117),char(108),char(115),char(101),char(0),char(109),char(95),char(108),char(111),
-char(119),char(101),char(114),char(76),char(105),char(109),char(105),char(116),char(0),char(109),char(95),char(117),char(112),char(112),char(101),char(114),char(76),char(105),char(109),char(105),
-char(116),char(0),char(109),char(95),char(108),char(105),char(109),char(105),char(116),char(83),char(111),char(102),char(116),char(110),char(101),char(115),char(115),char(0),char(109),char(95),
-char(98),char(105),char(97),char(115),char(70),char(97),char(99),char(116),char(111),char(114),char(0),char(109),char(95),char(114),char(101),char(108),char(97),char(120),char(97),char(116),
-char(105),char(111),char(110),char(70),char(97),char(99),char(116),char(111),char(114),char(0),char(109),char(95),char(112),char(97),char(100),char(100),char(105),char(110),char(103),char(49),
-char(91),char(52),char(93),char(0),char(109),char(95),char(115),char(119),char(105),char(110),char(103),char(83),char(112),char(97),char(110),char(49),char(0),char(109),char(95),char(115),
-char(119),char(105),char(110),char(103),char(83),char(112),char(97),char(110),char(50),char(0),char(109),char(95),char(116),char(119),char(105),char(115),char(116),char(83),char(112),char(97),
-char(110),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(85),char(112),char(112),char(101),char(114),char(76),char(105),char(109),char(105),char(116),
-char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(76),char(111),char(119),char(101),char(114),char(76),char(105),char(109),char(105),char(116),char(0),
-char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(85),char(112),char(112),char(101),char(114),char(76),char(105),char(109),char(105),char(116),char(0),
-char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(76),char(111),char(119),char(101),char(114),char(76),char(105),char(109),char(105),char(116),char(0),
-char(109),char(95),char(117),char(115),char(101),char(76),char(105),char(110),char(101),char(97),char(114),char(82),char(101),char(102),char(101),char(114),char(101),char(110),char(99),char(101),
-char(70),char(114),char(97),char(109),char(101),char(65),char(0),char(109),char(95),char(117),char(115),char(101),char(79),char(102),char(102),char(115),char(101),char(116),char(70),char(111),
-char(114),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(70),char(114),char(97),char(109),char(101),char(0),char(109),char(95),char(54),
-char(100),char(111),char(102),char(68),char(97),char(116),char(97),char(0),char(109),char(95),char(115),char(112),char(114),char(105),char(110),char(103),char(69),char(110),char(97),char(98),
-char(108),char(101),char(100),char(91),char(54),char(93),char(0),char(109),char(95),char(101),char(113),char(117),char(105),char(108),char(105),char(98),char(114),char(105),char(117),char(109),
-char(80),char(111),char(105),char(110),char(116),char(91),char(54),char(93),char(0),char(109),char(95),char(115),char(112),char(114),char(105),char(110),char(103),char(83),char(116),char(105),
-char(102),char(102),char(110),char(101),char(115),char(115),char(91),char(54),char(93),char(0),char(109),char(95),char(115),char(112),char(114),char(105),char(110),char(103),char(68),char(97),
-char(109),char(112),char(105),char(110),char(103),char(91),char(54),char(93),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(66),char(111),char(117),
-char(110),char(99),char(101),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(83),char(116),char(111),char(112),char(69),char(82),char(80),char(0),
-char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(83),char(116),char(111),char(112),char(67),char(70),char(77),char(0),char(109),char(95),char(108),char(105),
-char(110),char(101),char(97),char(114),char(77),char(111),char(116),char(111),char(114),char(69),char(82),char(80),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),
-char(114),char(77),char(111),char(116),char(111),char(114),char(67),char(70),char(77),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(84),char(97),
-char(114),char(103),char(101),char(116),char(86),char(101),char(108),char(111),char(99),char(105),char(116),char(121),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),
-char(114),char(77),char(97),char(120),char(77),char(111),char(116),char(111),char(114),char(70),char(111),char(114),char(99),char(101),char(0),char(109),char(95),char(108),char(105),char(110),
-char(101),char(97),char(114),char(83),char(101),char(114),char(118),char(111),char(84),char(97),char(114),char(103),char(101),char(116),char(0),char(109),char(95),char(108),char(105),char(110),
-char(101),char(97),char(114),char(83),char(112),char(114),char(105),char(110),char(103),char(83),char(116),char(105),char(102),char(102),char(110),char(101),char(115),char(115),char(0),char(109),
-char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(83),char(112),char(114),char(105),char(110),char(103),char(68),char(97),char(109),char(112),char(105),char(110),char(103),
-char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(69),char(113),char(117),char(105),char(108),char(105),char(98),char(114),char(105),char(117),char(109),
-char(80),char(111),char(105),char(110),char(116),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(69),char(110),char(97),char(98),char(108),char(101),
-char(77),char(111),char(116),char(111),char(114),char(91),char(52),char(93),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(83),char(101),char(114),
-char(118),char(111),char(77),char(111),char(116),char(111),char(114),char(91),char(52),char(93),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(69),
-char(110),char(97),char(98),char(108),char(101),char(83),char(112),char(114),char(105),char(110),char(103),char(91),char(52),char(93),char(0),char(109),char(95),char(108),char(105),char(110),
-char(101),char(97),char(114),char(83),char(112),char(114),char(105),char(110),char(103),char(83),char(116),char(105),char(102),char(102),char(110),char(101),char(115),char(115),char(76),char(105),
-char(109),char(105),char(116),char(101),char(100),char(91),char(52),char(93),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(83),char(112),char(114),
-char(105),char(110),char(103),char(68),char(97),char(109),char(112),char(105),char(110),char(103),char(76),char(105),char(109),char(105),char(116),char(101),char(100),char(91),char(52),char(93),
-char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(66),char(111),char(117),char(110),char(99),char(101),char(0),char(109),char(95),char(97),
-char(110),char(103),char(117),char(108),char(97),char(114),char(83),char(116),char(111),char(112),char(69),char(82),char(80),char(0),char(109),char(95),char(97),char(110),char(103),char(117),
-char(108),char(97),char(114),char(83),char(116),char(111),char(112),char(67),char(70),char(77),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),
-char(77),char(111),char(116),char(111),char(114),char(69),char(82),char(80),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(77),char(111),
-char(116),char(111),char(114),char(67),char(70),char(77),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(84),char(97),char(114),char(103),
-char(101),char(116),char(86),char(101),char(108),char(111),char(99),char(105),char(116),char(121),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),
-char(77),char(97),char(120),char(77),char(111),char(116),char(111),char(114),char(70),char(111),char(114),char(99),char(101),char(0),char(109),char(95),char(97),char(110),char(103),char(117),
-char(108),char(97),char(114),char(83),char(101),char(114),char(118),char(111),char(84),char(97),char(114),char(103),char(101),char(116),char(0),char(109),char(95),char(97),char(110),char(103),
-char(117),char(108),char(97),char(114),char(83),char(112),char(114),char(105),char(110),char(103),char(83),char(116),char(105),char(102),char(102),char(110),char(101),char(115),char(115),char(0),
-char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(83),char(112),char(114),char(105),char(110),char(103),char(68),char(97),char(109),char(112),char(105),
-char(110),char(103),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(69),char(113),char(117),char(105),char(108),char(105),char(98),char(114),
-char(105),char(117),char(109),char(80),char(111),char(105),char(110),char(116),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(69),char(110),
-char(97),char(98),char(108),char(101),char(77),char(111),char(116),char(111),char(114),char(91),char(52),char(93),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),
-char(97),char(114),char(83),char(101),char(114),char(118),char(111),char(77),char(111),char(116),char(111),char(114),char(91),char(52),char(93),char(0),char(109),char(95),char(97),char(110),
-char(103),char(117),char(108),char(97),char(114),char(69),char(110),char(97),char(98),char(108),char(101),char(83),char(112),char(114),char(105),char(110),char(103),char(91),char(52),char(93),
-char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(83),char(112),char(114),char(105),char(110),char(103),char(83),char(116),char(105),char(102),
-char(102),char(110),char(101),char(115),char(115),char(76),char(105),char(109),char(105),char(116),char(101),char(100),char(91),char(52),char(93),char(0),char(109),char(95),char(97),char(110),
-char(103),char(117),char(108),char(97),char(114),char(83),char(112),char(114),char(105),char(110),char(103),char(68),char(97),char(109),char(112),char(105),char(110),char(103),char(76),char(105),
-char(109),char(105),char(116),char(101),char(100),char(91),char(52),char(93),char(0),char(109),char(95),char(114),char(111),char(116),char(97),char(116),char(101),char(79),char(114),char(100),
-char(101),char(114),char(0),char(109),char(95),char(97),char(120),char(105),char(115),char(73),char(110),char(65),char(0),char(109),char(95),char(97),char(120),char(105),char(115),char(73),
-char(110),char(66),char(0),char(109),char(95),char(114),char(97),char(116),char(105),char(111),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(83),
-char(116),char(105),char(102),char(102),char(110),char(101),char(115),char(115),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(83),char(116),
-char(105),char(102),char(102),char(110),char(101),char(115),char(115),char(0),char(109),char(95),char(118),char(111),char(108),char(117),char(109),char(101),char(83),char(116),char(105),char(102),
-char(102),char(110),char(101),char(115),char(115),char(0),char(42),char(109),char(95),char(109),char(97),char(116),char(101),char(114),char(105),char(97),char(108),char(0),char(109),char(95),
-char(112),char(111),char(115),char(105),char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(112),char(114),char(101),char(118),char(105),char(111),char(117),char(115),char(80),
-char(111),char(115),char(105),char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(118),char(101),char(108),char(111),char(99),char(105),char(116),char(121),char(0),char(109),
-char(95),char(97),char(99),char(99),char(117),char(109),char(117),char(108),char(97),char(116),char(101),char(100),char(70),char(111),char(114),char(99),char(101),char(0),char(109),char(95),
-char(110),char(111),char(114),char(109),char(97),char(108),char(0),char(109),char(95),char(97),char(114),char(101),char(97),char(0),char(109),char(95),char(97),char(116),char(116),char(97),
-char(99),char(104),char(0),char(109),char(95),char(110),char(111),char(100),char(101),char(73),char(110),char(100),char(105),char(99),char(101),char(115),char(91),char(50),char(93),char(0),
-char(109),char(95),char(114),char(101),char(115),char(116),char(76),char(101),char(110),char(103),char(116),char(104),char(0),char(109),char(95),char(98),char(98),char(101),char(110),char(100),
-char(105),char(110),char(103),char(0),char(109),char(95),char(110),char(111),char(100),char(101),char(73),char(110),char(100),char(105),char(99),char(101),char(115),char(91),char(51),char(93),
-char(0),char(109),char(95),char(114),char(101),char(115),char(116),char(65),char(114),char(101),char(97),char(0),char(109),char(95),char(99),char(48),char(91),char(52),char(93),char(0),
-char(109),char(95),char(110),char(111),char(100),char(101),char(73),char(110),char(100),char(105),char(99),char(101),char(115),char(91),char(52),char(93),char(0),char(109),char(95),char(114),
-char(101),char(115),char(116),char(86),char(111),char(108),char(117),char(109),char(101),char(0),char(109),char(95),char(99),char(49),char(0),char(109),char(95),char(99),char(50),char(0),
-char(109),char(95),char(99),char(48),char(0),char(109),char(95),char(108),char(111),char(99),char(97),char(108),char(70),char(114),char(97),char(109),char(101),char(0),char(42),char(109),
-char(95),char(114),char(105),char(103),char(105),char(100),char(66),char(111),char(100),char(121),char(0),char(109),char(95),char(110),char(111),char(100),char(101),char(73),char(110),char(100),
-char(101),char(120),char(0),char(109),char(95),char(97),char(101),char(114),char(111),char(77),char(111),char(100),char(101),char(108),char(0),char(109),char(95),char(98),char(97),char(117),
-char(109),char(103),char(97),char(114),char(116),char(101),char(0),char(109),char(95),char(100),char(114),char(97),char(103),char(0),char(109),char(95),char(108),char(105),char(102),char(116),
-char(0),char(109),char(95),char(112),char(114),char(101),char(115),char(115),char(117),char(114),char(101),char(0),char(109),char(95),char(118),char(111),char(108),char(117),char(109),char(101),
-char(0),char(109),char(95),char(100),char(121),char(110),char(97),char(109),char(105),char(99),char(70),char(114),char(105),char(99),char(116),char(105),char(111),char(110),char(0),char(109),
-char(95),char(112),char(111),char(115),char(101),char(77),char(97),char(116),char(99),char(104),char(0),char(109),char(95),char(114),char(105),char(103),char(105),char(100),char(67),char(111),
-char(110),char(116),char(97),char(99),char(116),char(72),char(97),char(114),char(100),char(110),char(101),char(115),char(115),char(0),char(109),char(95),char(107),char(105),char(110),char(101),
-char(116),char(105),char(99),char(67),char(111),char(110),char(116),char(97),char(99),char(116),char(72),char(97),char(114),char(100),char(110),char(101),char(115),char(115),char(0),char(109),
-char(95),char(115),char(111),char(102),char(116),char(67),char(111),char(110),char(116),char(97),char(99),char(116),char(72),char(97),char(114),char(100),char(110),char(101),char(115),char(115),
-char(0),char(109),char(95),char(97),char(110),char(99),char(104),char(111),char(114),char(72),char(97),char(114),char(100),char(110),char(101),char(115),char(115),char(0),char(109),char(95),
-char(115),char(111),char(102),char(116),char(82),char(105),char(103),char(105),char(100),char(67),char(108),char(117),char(115),char(116),char(101),char(114),char(72),char(97),char(114),char(100),
-char(110),char(101),char(115),char(115),char(0),char(109),char(95),char(115),char(111),char(102),char(116),char(75),char(105),char(110),char(101),char(116),char(105),char(99),char(67),char(108),
-char(117),char(115),char(116),char(101),char(114),char(72),char(97),char(114),char(100),char(110),char(101),char(115),char(115),char(0),char(109),char(95),char(115),char(111),char(102),char(116),
-char(83),char(111),char(102),char(116),char(67),char(108),char(117),char(115),char(116),char(101),char(114),char(72),char(97),char(114),char(100),char(110),char(101),char(115),char(115),char(0),
-char(109),char(95),char(115),char(111),char(102),char(116),char(82),char(105),char(103),char(105),char(100),char(67),char(108),char(117),char(115),char(116),char(101),char(114),char(73),char(109),
-char(112),char(117),char(108),char(115),char(101),char(83),char(112),char(108),char(105),char(116),char(0),char(109),char(95),char(115),char(111),char(102),char(116),char(75),char(105),char(110),
-char(101),char(116),char(105),char(99),char(67),char(108),char(117),char(115),char(116),char(101),char(114),char(73),char(109),char(112),char(117),char(108),char(115),char(101),char(83),char(112),
-char(108),char(105),char(116),char(0),char(109),char(95),char(115),char(111),char(102),char(116),char(83),char(111),char(102),char(116),char(67),char(108),char(117),char(115),char(116),char(101),
-char(114),char(73),char(109),char(112),char(117),char(108),char(115),char(101),char(83),char(112),char(108),char(105),char(116),char(0),char(109),char(95),char(109),char(97),char(120),char(86),
-char(111),char(108),char(117),char(109),char(101),char(0),char(109),char(95),char(116),char(105),char(109),char(101),char(83),char(99),char(97),char(108),char(101),char(0),char(109),char(95),
-char(118),char(101),char(108),char(111),char(99),char(105),char(116),char(121),char(73),char(116),char(101),char(114),char(97),char(116),char(105),char(111),char(110),char(115),char(0),char(109),
-char(95),char(112),char(111),char(115),char(105),char(116),char(105),char(111),char(110),char(73),char(116),char(101),char(114),char(97),char(116),char(105),char(111),char(110),char(115),char(0),
-char(109),char(95),char(100),char(114),char(105),char(102),char(116),char(73),char(116),char(101),char(114),char(97),char(116),char(105),char(111),char(110),char(115),char(0),char(109),char(95),
-char(99),char(108),char(117),char(115),char(116),char(101),char(114),char(73),char(116),char(101),char(114),char(97),char(116),char(105),char(111),char(110),char(115),char(0),char(109),char(95),
-char(114),char(111),char(116),char(0),char(109),char(95),char(115),char(99),char(97),char(108),char(101),char(0),char(109),char(95),char(97),char(113),char(113),char(0),char(109),char(95),
-char(99),char(111),char(109),char(0),char(42),char(109),char(95),char(112),char(111),char(115),char(105),char(116),char(105),char(111),char(110),char(115),char(0),char(42),char(109),char(95),
-char(119),char(101),char(105),char(103),char(104),char(116),char(115),char(0),char(109),char(95),char(110),char(117),char(109),char(80),char(111),char(115),char(105),char(116),char(105),char(111),
-char(110),char(115),char(0),char(109),char(95),char(110),char(117),char(109),char(87),char(101),char(105),char(103),char(116),char(115),char(0),char(109),char(95),char(98),char(118),char(111),
-char(108),char(117),char(109),char(101),char(0),char(109),char(95),char(98),char(102),char(114),char(97),char(109),char(101),char(0),char(109),char(95),char(102),char(114),char(97),char(109),
-char(101),char(120),char(102),char(111),char(114),char(109),char(0),char(109),char(95),char(108),char(111),char(99),char(105),char(105),char(0),char(109),char(95),char(105),char(110),char(118),
-char(119),char(105),char(0),char(109),char(95),char(118),char(105),char(109),char(112),char(117),char(108),char(115),char(101),char(115),char(91),char(50),char(93),char(0),char(109),char(95),
-char(100),char(105),char(109),char(112),char(117),char(108),char(115),char(101),char(115),char(91),char(50),char(93),char(0),char(109),char(95),char(108),char(118),char(0),char(109),char(95),
-char(97),char(118),char(0),char(42),char(109),char(95),char(102),char(114),char(97),char(109),char(101),char(114),char(101),char(102),char(115),char(0),char(42),char(109),char(95),char(110),
-char(111),char(100),char(101),char(73),char(110),char(100),char(105),char(99),char(101),char(115),char(0),char(42),char(109),char(95),char(109),char(97),char(115),char(115),char(101),char(115),
-char(0),char(109),char(95),char(110),char(117),char(109),char(70),char(114),char(97),char(109),char(101),char(82),char(101),char(102),char(115),char(0),char(109),char(95),char(110),char(117),
-char(109),char(78),char(111),char(100),char(101),char(115),char(0),char(109),char(95),char(110),char(117),char(109),char(77),char(97),char(115),char(115),char(101),char(115),char(0),char(109),
-char(95),char(105),char(100),char(109),char(97),char(115),char(115),char(0),char(109),char(95),char(105),char(109),char(97),char(115),char(115),char(0),char(109),char(95),char(110),char(118),
-char(105),char(109),char(112),char(117),char(108),char(115),char(101),char(115),char(0),char(109),char(95),char(110),char(100),char(105),char(109),char(112),char(117),char(108),char(115),char(101),
-char(115),char(0),char(109),char(95),char(110),char(100),char(97),char(109),char(112),char(105),char(110),char(103),char(0),char(109),char(95),char(108),char(100),char(97),char(109),char(112),
-char(105),char(110),char(103),char(0),char(109),char(95),char(97),char(100),char(97),char(109),char(112),char(105),char(110),char(103),char(0),char(109),char(95),char(109),char(97),char(116),
-char(99),char(104),char(105),char(110),char(103),char(0),char(109),char(95),char(109),char(97),char(120),char(83),char(101),char(108),char(102),char(67),char(111),char(108),char(108),char(105),
-char(115),char(105),char(111),char(110),char(73),char(109),char(112),char(117),char(108),char(115),char(101),char(0),char(109),char(95),char(115),char(101),char(108),char(102),char(67),char(111),
-char(108),char(108),char(105),char(115),char(105),char(111),char(110),char(73),char(109),char(112),char(117),char(108),char(115),char(101),char(70),char(97),char(99),char(116),char(111),char(114),
-char(0),char(109),char(95),char(99),char(111),char(110),char(116),char(97),char(105),char(110),char(115),char(65),char(110),char(99),char(104),char(111),char(114),char(0),char(109),char(95),
-char(99),char(111),char(108),char(108),char(105),char(100),char(101),char(0),char(109),char(95),char(99),char(108),char(117),char(115),char(116),char(101),char(114),char(73),char(110),char(100),
-char(101),char(120),char(0),char(42),char(109),char(95),char(98),char(111),char(100),char(121),char(65),char(0),char(42),char(109),char(95),char(98),char(111),char(100),char(121),char(66),
-char(0),char(109),char(95),char(114),char(101),char(102),char(115),char(91),char(50),char(93),char(0),char(109),char(95),char(99),char(102),char(109),char(0),char(109),char(95),char(115),
-char(112),char(108),char(105),char(116),char(0),char(109),char(95),char(100),char(101),char(108),char(101),char(116),char(101),char(0),char(109),char(95),char(114),char(101),char(108),char(80),
-char(111),char(115),char(105),char(116),char(105),char(111),char(110),char(91),char(50),char(93),char(0),char(109),char(95),char(98),char(111),char(100),char(121),char(65),char(116),char(121),
-char(112),char(101),char(0),char(109),char(95),char(98),char(111),char(100),char(121),char(66),char(116),char(121),char(112),char(101),char(0),char(109),char(95),char(106),char(111),char(105),
-char(110),char(116),char(84),char(121),char(112),char(101),char(0),char(42),char(109),char(95),char(112),char(111),char(115),char(101),char(0),char(42),char(42),char(109),char(95),char(109),
-char(97),char(116),char(101),char(114),char(105),char(97),char(108),char(115),char(0),char(42),char(109),char(95),char(110),char(111),char(100),char(101),char(115),char(0),char(42),char(109),
-char(95),char(108),char(105),char(110),char(107),char(115),char(0),char(42),char(109),char(95),char(102),char(97),char(99),char(101),char(115),char(0),char(42),char(109),char(95),char(116),
-char(101),char(116),char(114),char(97),char(104),char(101),char(100),char(114),char(97),char(0),char(42),char(109),char(95),char(97),char(110),char(99),char(104),char(111),char(114),char(115),
-char(0),char(42),char(109),char(95),char(99),char(108),char(117),char(115),char(116),char(101),char(114),char(115),char(0),char(42),char(109),char(95),char(106),char(111),char(105),char(110),
-char(116),char(115),char(0),char(109),char(95),char(110),char(117),char(109),char(77),char(97),char(116),char(101),char(114),char(105),char(97),char(108),char(115),char(0),char(109),char(95),
-char(110),char(117),char(109),char(76),char(105),char(110),char(107),char(115),char(0),char(109),char(95),char(110),char(117),char(109),char(70),char(97),char(99),char(101),char(115),char(0),
-char(109),char(95),char(110),char(117),char(109),char(84),char(101),char(116),char(114),char(97),char(104),char(101),char(100),char(114),char(97),char(0),char(109),char(95),char(110),char(117),
-char(109),char(65),char(110),char(99),char(104),char(111),char(114),char(115),char(0),char(109),char(95),char(110),char(117),char(109),char(67),char(108),char(117),char(115),char(116),char(101),
-char(114),char(115),char(0),char(109),char(95),char(110),char(117),char(109),char(74),char(111),char(105),char(110),char(116),char(115),char(0),char(109),char(95),char(99),char(111),char(110),
-char(102),char(105),char(103),char(0),char(109),char(95),char(122),char(101),char(114),char(111),char(82),char(111),char(116),char(80),char(97),char(114),char(101),char(110),char(116),char(84),
-char(111),char(84),char(104),char(105),char(115),char(0),char(109),char(95),char(112),char(97),char(114),char(101),char(110),char(116),char(67),char(111),char(109),char(84),char(111),char(84),
-char(104),char(105),char(115),char(80),char(105),char(118),char(111),char(116),char(79),char(102),char(102),char(115),char(101),char(116),char(0),char(109),char(95),char(116),char(104),char(105),
-char(115),char(80),char(105),char(118),char(111),char(116),char(84),char(111),char(84),char(104),char(105),char(115),char(67),char(111),char(109),char(79),char(102),char(102),char(115),char(101),
-char(116),char(0),char(109),char(95),char(106),char(111),char(105),char(110),char(116),char(65),char(120),char(105),char(115),char(84),char(111),char(112),char(91),char(54),char(93),char(0),
-char(109),char(95),char(106),char(111),char(105),char(110),char(116),char(65),char(120),char(105),char(115),char(66),char(111),char(116),char(116),char(111),char(109),char(91),char(54),char(93),
-char(0),char(109),char(95),char(108),char(105),char(110),char(107),char(73),char(110),char(101),char(114),char(116),char(105),char(97),char(0),char(109),char(95),char(97),char(98),char(115),
-char(70),char(114),char(97),char(109),char(101),char(84),char(111),char(116),char(86),char(101),char(108),char(111),char(99),char(105),char(116),char(121),char(84),char(111),char(112),char(0),
-char(109),char(95),char(97),char(98),char(115),char(70),char(114),char(97),char(109),char(101),char(84),char(111),char(116),char(86),char(101),char(108),char(111),char(99),char(105),char(116),
-char(121),char(66),char(111),char(116),char(116),char(111),char(109),char(0),char(109),char(95),char(97),char(98),char(115),char(70),char(114),char(97),char(109),char(101),char(76),char(111),
-char(99),char(86),char(101),char(108),char(111),char(99),char(105),char(116),char(121),char(84),char(111),char(112),char(0),char(109),char(95),char(97),char(98),char(115),char(70),char(114),
-char(97),char(109),char(101),char(76),char(111),char(99),char(86),char(101),char(108),char(111),char(99),char(105),char(116),char(121),char(66),char(111),char(116),char(116),char(111),char(109),
-char(0),char(109),char(95),char(108),char(105),char(110),char(107),char(77),char(97),char(115),char(115),char(0),char(109),char(95),char(112),char(97),char(114),char(101),char(110),char(116),
-char(73),char(110),char(100),char(101),char(120),char(0),char(109),char(95),char(100),char(111),char(102),char(67),char(111),char(117),char(110),char(116),char(0),char(109),char(95),char(112),
-char(111),char(115),char(86),char(97),char(114),char(67),char(111),char(117),char(110),char(116),char(0),char(109),char(95),char(106),char(111),char(105),char(110),char(116),char(80),char(111),
-char(115),char(91),char(55),char(93),char(0),char(109),char(95),char(106),char(111),char(105),char(110),char(116),char(86),char(101),char(108),char(91),char(54),char(93),char(0),char(109),
-char(95),char(106),char(111),char(105),char(110),char(116),char(84),char(111),char(114),char(113),char(117),char(101),char(91),char(54),char(93),char(0),char(109),char(95),char(106),char(111),
-char(105),char(110),char(116),char(68),char(97),char(109),char(112),char(105),char(110),char(103),char(0),char(109),char(95),char(106),char(111),char(105),char(110),char(116),char(70),char(114),
-char(105),char(99),char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(106),char(111),char(105),char(110),char(116),char(76),char(111),char(119),char(101),char(114),char(76),
-char(105),char(109),char(105),char(116),char(0),char(109),char(95),char(106),char(111),char(105),char(110),char(116),char(85),char(112),char(112),char(101),char(114),char(76),char(105),char(109),
-char(105),char(116),char(0),char(109),char(95),char(106),char(111),char(105),char(110),char(116),char(77),char(97),char(120),char(70),char(111),char(114),char(99),char(101),char(0),char(109),
-char(95),char(106),char(111),char(105),char(110),char(116),char(77),char(97),char(120),char(86),char(101),char(108),char(111),char(99),char(105),char(116),char(121),char(0),char(42),char(109),
-char(95),char(108),char(105),char(110),char(107),char(78),char(97),char(109),char(101),char(0),char(42),char(109),char(95),char(106),char(111),char(105),char(110),char(116),char(78),char(97),
-char(109),char(101),char(0),char(42),char(109),char(95),char(108),char(105),char(110),char(107),char(67),char(111),char(108),char(108),char(105),char(100),char(101),char(114),char(0),char(42),
-char(109),char(95),char(112),char(97),char(100),char(100),char(105),char(110),char(103),char(80),char(116),char(114),char(0),char(109),char(95),char(98),char(97),char(115),char(101),char(87),
-char(111),char(114),char(108),char(100),char(80),char(111),char(115),char(105),char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(98),char(97),char(115),char(101),char(87),
-char(111),char(114),char(108),char(100),char(79),char(114),char(105),char(101),char(110),char(116),char(97),char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(98),char(97),
-char(115),char(101),char(76),char(105),char(110),char(101),char(97),char(114),char(86),char(101),char(108),char(111),char(99),char(105),char(116),char(121),char(0),char(109),char(95),char(98),
-char(97),char(115),char(101),char(65),char(110),char(103),char(117),char(108),char(97),char(114),char(86),char(101),char(108),char(111),char(99),char(105),char(116),char(121),char(0),char(109),
-char(95),char(98),char(97),char(115),char(101),char(73),char(110),char(101),char(114),char(116),char(105),char(97),char(0),char(109),char(95),char(98),char(97),char(115),char(101),char(77),
-char(97),char(115),char(115),char(0),char(42),char(109),char(95),char(98),char(97),char(115),char(101),char(78),char(97),char(109),char(101),char(0),char(42),char(109),char(95),char(98),
-char(97),char(115),char(101),char(67),char(111),char(108),char(108),char(105),char(100),char(101),char(114),char(0),char(109),char(95),char(99),char(111),char(108),char(79),char(98),char(106),
-char(68),char(97),char(116),char(97),char(0),char(42),char(109),char(95),char(109),char(117),char(108),char(116),char(105),char(66),char(111),char(100),char(121),char(0),char(109),char(95),
-char(108),char(105),char(110),char(107),char(0),char(0),char(0),char(0),char(84),char(89),char(80),char(69),char(99),char(0),char(0),char(0),char(99),char(104),char(97),char(114),
-char(0),char(117),char(99),char(104),char(97),char(114),char(0),char(115),char(104),char(111),char(114),char(116),char(0),char(117),char(115),char(104),char(111),char(114),char(116),char(0),
-char(105),char(110),char(116),char(0),char(108),char(111),char(110),char(103),char(0),char(117),char(108),char(111),char(110),char(103),char(0),char(102),char(108),char(111),char(97),char(116),
-char(0),char(100),char(111),char(117),char(98),char(108),char(101),char(0),char(118),char(111),char(105),char(100),char(0),char(80),char(111),char(105),char(110),char(116),char(101),char(114),
-char(65),char(114),char(114),char(97),char(121),char(0),char(98),char(116),char(80),char(104),char(121),char(115),char(105),char(99),char(115),char(83),char(121),char(115),char(116),char(101),
-char(109),char(0),char(76),char(105),char(115),char(116),char(66),char(97),char(115),char(101),char(0),char(98),char(116),char(86),char(101),char(99),char(116),char(111),char(114),char(51),
-char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(86),char(101),char(99),char(116),char(111),char(114),char(51),char(68),
-char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(81),char(117),char(97),char(116),char(101),char(114),char(110),char(105),
-char(111),char(110),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(81),char(117),char(97),char(116),char(101),char(114),
-char(110),char(105),char(111),char(110),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(77),char(97),char(116),
-char(114),char(105),char(120),char(51),char(120),char(51),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(77),char(97),
-char(116),char(114),char(105),char(120),char(51),char(120),char(51),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),
-char(84),char(114),char(97),char(110),char(115),char(102),char(111),char(114),char(109),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),
-char(116),char(84),char(114),char(97),char(110),char(115),char(102),char(111),char(114),char(109),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),
-char(0),char(98),char(116),char(66),char(118),char(104),char(83),char(117),char(98),char(116),char(114),char(101),char(101),char(73),char(110),char(102),char(111),char(68),char(97),char(116),
+char(112),char(111),char(105),char(110),char(116),char(67),char(97),char(99),char(104),char(101),char(80),char(114),char(101),char(118),char(82),char(72),char(83),char(91),char(52),char(93),
+char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),char(67),char(97),char(99),char(104),char(101),char(67),char(111),char(109),char(98),char(105),char(110),char(101),
+char(100),char(70),char(114),char(105),char(99),char(116),char(105),char(111),char(110),char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),
+char(67),char(97),char(99),char(104),char(101),char(67),char(111),char(109),char(98),char(105),char(110),char(101),char(100),char(82),char(111),char(108),char(108),char(105),char(110),char(103),
+char(70),char(114),char(105),char(99),char(116),char(105),char(111),char(110),char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),char(67),
+char(97),char(99),char(104),char(101),char(67),char(111),char(109),char(98),char(105),char(110),char(101),char(100),char(83),char(112),char(105),char(110),char(110),char(105),char(110),char(103),
+char(70),char(114),char(105),char(99),char(116),char(105),char(111),char(110),char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),char(67),
+char(97),char(99),char(104),char(101),char(67),char(111),char(109),char(98),char(105),char(110),char(101),char(100),char(82),char(101),char(115),char(116),char(105),char(116),char(117),char(116),
+char(105),char(111),char(110),char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),char(67),char(97),char(99),char(104),char(101),char(80),
+char(97),char(114),char(116),char(73),char(100),char(48),char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),char(67),char(97),char(99),
+char(104),char(101),char(80),char(97),char(114),char(116),char(73),char(100),char(49),char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),
+char(67),char(97),char(99),char(104),char(101),char(73),char(110),char(100),char(101),char(120),char(48),char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),
+char(110),char(116),char(67),char(97),char(99),char(104),char(101),char(73),char(110),char(100),char(101),char(120),char(49),char(91),char(52),char(93),char(0),char(109),char(95),char(112),
+char(111),char(105),char(110),char(116),char(67),char(97),char(99),char(104),char(101),char(67),char(111),char(110),char(116),char(97),char(99),char(116),char(80),char(111),char(105),char(110),
+char(116),char(70),char(108),char(97),char(103),char(115),char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),char(67),char(97),char(99),
+char(104),char(101),char(65),char(112),char(112),char(108),char(105),char(101),char(100),char(73),char(109),char(112),char(117),char(108),char(115),char(101),char(76),char(97),char(116),char(101),
+char(114),char(97),char(108),char(49),char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),char(67),char(97),char(99),char(104),char(101),
+char(65),char(112),char(112),char(108),char(105),char(101),char(100),char(73),char(109),char(112),char(117),char(108),char(115),char(101),char(76),char(97),char(116),char(101),char(114),char(97),
+char(108),char(50),char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),char(67),char(97),char(99),char(104),char(101),char(67),char(111),
+char(110),char(116),char(97),char(99),char(116),char(77),char(111),char(116),char(105),char(111),char(110),char(49),char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),
+char(105),char(110),char(116),char(67),char(97),char(99),char(104),char(101),char(67),char(111),char(110),char(116),char(97),char(99),char(116),char(77),char(111),char(116),char(105),char(111),
+char(110),char(50),char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),char(67),char(97),char(99),char(104),char(101),char(67),char(111),
+char(110),char(116),char(97),char(99),char(116),char(67),char(70),char(77),char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),char(67),
+char(97),char(99),char(104),char(101),char(67),char(111),char(109),char(98),char(105),char(110),char(101),char(100),char(67),char(111),char(110),char(116),char(97),char(99),char(116),char(83),
+char(116),char(105),char(102),char(102),char(110),char(101),char(115),char(115),char(49),char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),
+char(67),char(97),char(99),char(104),char(101),char(67),char(111),char(110),char(116),char(97),char(99),char(116),char(69),char(82),char(80),char(91),char(52),char(93),char(0),char(109),
+char(95),char(112),char(111),char(105),char(110),char(116),char(67),char(97),char(99),char(104),char(101),char(67),char(111),char(109),char(98),char(105),char(110),char(101),char(100),char(67),
+char(111),char(110),char(116),char(97),char(99),char(116),char(68),char(97),char(109),char(112),char(105),char(110),char(103),char(49),char(91),char(52),char(93),char(0),char(109),char(95),
+char(112),char(111),char(105),char(110),char(116),char(67),char(97),char(99),char(104),char(101),char(70),char(114),char(105),char(99),char(116),char(105),char(111),char(110),char(67),char(70),
+char(77),char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),char(67),char(97),char(99),char(104),char(101),char(76),char(105),char(102),
+char(101),char(84),char(105),char(109),char(101),char(91),char(52),char(93),char(0),char(109),char(95),char(110),char(117),char(109),char(67),char(97),char(99),char(104),char(101),char(100),
+char(80),char(111),char(105),char(110),char(116),char(115),char(0),char(109),char(95),char(99),char(111),char(109),char(112),char(97),char(110),char(105),char(111),char(110),char(73),char(100),
+char(65),char(0),char(109),char(95),char(99),char(111),char(109),char(112),char(97),char(110),char(105),char(111),char(110),char(73),char(100),char(66),char(0),char(109),char(95),char(105),
+char(110),char(100),char(101),char(120),char(49),char(97),char(0),char(109),char(95),char(111),char(98),char(106),char(101),char(99),char(116),char(84),char(121),char(112),char(101),char(0),
+char(109),char(95),char(99),char(111),char(110),char(116),char(97),char(99),char(116),char(66),char(114),char(101),char(97),char(107),char(105),char(110),char(103),char(84),char(104),char(114),
+char(101),char(115),char(104),char(111),char(108),char(100),char(0),char(109),char(95),char(99),char(111),char(110),char(116),char(97),char(99),char(116),char(80),char(114),char(111),char(99),
+char(101),char(115),char(115),char(105),char(110),char(103),char(84),char(104),char(114),char(101),char(115),char(104),char(111),char(108),char(100),char(0),char(42),char(109),char(95),char(98),
+char(111),char(100),char(121),char(48),char(0),char(42),char(109),char(95),char(98),char(111),char(100),char(121),char(49),char(0),char(109),char(95),char(103),char(105),char(109),char(112),
+char(97),char(99),char(116),char(83),char(117),char(98),char(84),char(121),char(112),char(101),char(0),char(42),char(109),char(95),char(117),char(110),char(115),char(99),char(97),char(108),
+char(101),char(100),char(80),char(111),char(105),char(110),char(116),char(115),char(70),char(108),char(111),char(97),char(116),char(80),char(116),char(114),char(0),char(42),char(109),char(95),
+char(117),char(110),char(115),char(99),char(97),char(108),char(101),char(100),char(80),char(111),char(105),char(110),char(116),char(115),char(68),char(111),char(117),char(98),char(108),char(101),
+char(80),char(116),char(114),char(0),char(109),char(95),char(110),char(117),char(109),char(85),char(110),char(115),char(99),char(97),char(108),char(101),char(100),char(80),char(111),char(105),
+char(110),char(116),char(115),char(0),char(109),char(95),char(112),char(97),char(100),char(100),char(105),char(110),char(103),char(51),char(91),char(52),char(93),char(0),char(42),char(109),
+char(95),char(98),char(114),char(111),char(97),char(100),char(112),char(104),char(97),char(115),char(101),char(72),char(97),char(110),char(100),char(108),char(101),char(0),char(42),char(109),
+char(95),char(99),char(111),char(108),char(108),char(105),char(115),char(105),char(111),char(110),char(83),char(104),char(97),char(112),char(101),char(0),char(42),char(109),char(95),char(114),
+char(111),char(111),char(116),char(67),char(111),char(108),char(108),char(105),char(115),char(105),char(111),char(110),char(83),char(104),char(97),char(112),char(101),char(0),char(109),char(95),
+char(119),char(111),char(114),char(108),char(100),char(84),char(114),char(97),char(110),char(115),char(102),char(111),char(114),char(109),char(0),char(109),char(95),char(105),char(110),char(116),
+char(101),char(114),char(112),char(111),char(108),char(97),char(116),char(105),char(111),char(110),char(87),char(111),char(114),char(108),char(100),char(84),char(114),char(97),char(110),char(115),
+char(102),char(111),char(114),char(109),char(0),char(109),char(95),char(105),char(110),char(116),char(101),char(114),char(112),char(111),char(108),char(97),char(116),char(105),char(111),char(110),
+char(76),char(105),char(110),char(101),char(97),char(114),char(86),char(101),char(108),char(111),char(99),char(105),char(116),char(121),char(0),char(109),char(95),char(105),char(110),char(116),
+char(101),char(114),char(112),char(111),char(108),char(97),char(116),char(105),char(111),char(110),char(65),char(110),char(103),char(117),char(108),char(97),char(114),char(86),char(101),char(108),
+char(111),char(99),char(105),char(116),char(121),char(0),char(109),char(95),char(97),char(110),char(105),char(115),char(111),char(116),char(114),char(111),char(112),char(105),char(99),char(70),
+char(114),char(105),char(99),char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(100),char(101),char(97),char(99),char(116),char(105),char(118),char(97),char(116),char(105),
+char(111),char(110),char(84),char(105),char(109),char(101),char(0),char(109),char(95),char(102),char(114),char(105),char(99),char(116),char(105),char(111),char(110),char(0),char(109),char(95),
+char(114),char(111),char(108),char(108),char(105),char(110),char(103),char(70),char(114),char(105),char(99),char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(99),char(111),
+char(110),char(116),char(97),char(99),char(116),char(68),char(97),char(109),char(112),char(105),char(110),char(103),char(0),char(109),char(95),char(99),char(111),char(110),char(116),char(97),
+char(99),char(116),char(83),char(116),char(105),char(102),char(102),char(110),char(101),char(115),char(115),char(0),char(109),char(95),char(114),char(101),char(115),char(116),char(105),char(116),
+char(117),char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(104),char(105),char(116),char(70),char(114),char(97),char(99),char(116),char(105),char(111),char(110),char(0),
+char(109),char(95),char(99),char(99),char(100),char(83),char(119),char(101),char(112),char(116),char(83),char(112),char(104),char(101),char(114),char(101),char(82),char(97),char(100),char(105),
+char(117),char(115),char(0),char(109),char(95),char(99),char(99),char(100),char(77),char(111),char(116),char(105),char(111),char(110),char(84),char(104),char(114),char(101),char(115),char(104),
+char(111),char(108),char(100),char(0),char(109),char(95),char(104),char(97),char(115),char(65),char(110),char(105),char(115),char(111),char(116),char(114),char(111),char(112),char(105),char(99),
+char(70),char(114),char(105),char(99),char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(99),char(111),char(108),char(108),char(105),char(115),char(105),char(111),char(110),
+char(70),char(108),char(97),char(103),char(115),char(0),char(109),char(95),char(105),char(115),char(108),char(97),char(110),char(100),char(84),char(97),char(103),char(49),char(0),char(109),
+char(95),char(99),char(111),char(109),char(112),char(97),char(110),char(105),char(111),char(110),char(73),char(100),char(0),char(109),char(95),char(97),char(99),char(116),char(105),char(118),
+char(97),char(116),char(105),char(111),char(110),char(83),char(116),char(97),char(116),char(101),char(49),char(0),char(109),char(95),char(105),char(110),char(116),char(101),char(114),char(110),
+char(97),char(108),char(84),char(121),char(112),char(101),char(0),char(109),char(95),char(99),char(104),char(101),char(99),char(107),char(67),char(111),char(108),char(108),char(105),char(100),
+char(101),char(87),char(105),char(116),char(104),char(0),char(109),char(95),char(99),char(111),char(108),char(108),char(105),char(115),char(105),char(111),char(110),char(70),char(105),char(108),
+char(116),char(101),char(114),char(71),char(114),char(111),char(117),char(112),char(0),char(109),char(95),char(99),char(111),char(108),char(108),char(105),char(115),char(105),char(111),char(110),
+char(70),char(105),char(108),char(116),char(101),char(114),char(77),char(97),char(115),char(107),char(0),char(109),char(95),char(117),char(110),char(105),char(113),char(117),char(101),char(73),
+char(100),char(0),char(109),char(95),char(116),char(97),char(117),char(0),char(109),char(95),char(100),char(97),char(109),char(112),char(105),char(110),char(103),char(0),char(109),char(95),
+char(116),char(105),char(109),char(101),char(83),char(116),char(101),char(112),char(0),char(109),char(95),char(109),char(97),char(120),char(69),char(114),char(114),char(111),char(114),char(82),
+char(101),char(100),char(117),char(99),char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(115),char(111),char(114),char(0),char(109),char(95),char(101),char(114),char(112),
+char(0),char(109),char(95),char(101),char(114),char(112),char(50),char(0),char(109),char(95),char(103),char(108),char(111),char(98),char(97),char(108),char(67),char(102),char(109),char(0),
+char(109),char(95),char(115),char(112),char(108),char(105),char(116),char(73),char(109),char(112),char(117),char(108),char(115),char(101),char(80),char(101),char(110),char(101),char(116),char(114),
+char(97),char(116),char(105),char(111),char(110),char(84),char(104),char(114),char(101),char(115),char(104),char(111),char(108),char(100),char(0),char(109),char(95),char(115),char(112),char(108),
+char(105),char(116),char(73),char(109),char(112),char(117),char(108),char(115),char(101),char(84),char(117),char(114),char(110),char(69),char(114),char(112),char(0),char(109),char(95),char(108),
+char(105),char(110),char(101),char(97),char(114),char(83),char(108),char(111),char(112),char(0),char(109),char(95),char(119),char(97),char(114),char(109),char(115),char(116),char(97),char(114),
+char(116),char(105),char(110),char(103),char(70),char(97),char(99),char(116),char(111),char(114),char(0),char(109),char(95),char(97),char(114),char(116),char(105),char(99),char(117),char(108),
+char(97),char(116),char(101),char(100),char(87),char(97),char(114),char(109),char(115),char(116),char(97),char(114),char(116),char(105),char(110),char(103),char(70),char(97),char(99),char(116),
+char(111),char(114),char(0),char(109),char(95),char(109),char(97),char(120),char(71),char(121),char(114),char(111),char(115),char(99),char(111),char(112),char(105),char(99),char(70),char(111),
+char(114),char(99),char(101),char(0),char(109),char(95),char(115),char(105),char(110),char(103),char(108),char(101),char(65),char(120),char(105),char(115),char(82),char(111),char(108),char(108),
+char(105),char(110),char(103),char(70),char(114),char(105),char(99),char(116),char(105),char(111),char(110),char(84),char(104),char(114),char(101),char(115),char(104),char(111),char(108),char(100),
+char(0),char(109),char(95),char(110),char(117),char(109),char(73),char(116),char(101),char(114),char(97),char(116),char(105),char(111),char(110),char(115),char(0),char(109),char(95),char(115),
+char(111),char(108),char(118),char(101),char(114),char(77),char(111),char(100),char(101),char(0),char(109),char(95),char(114),char(101),char(115),char(116),char(105),char(110),char(103),char(67),
+char(111),char(110),char(116),char(97),char(99),char(116),char(82),char(101),char(115),char(116),char(105),char(116),char(117),char(116),char(105),char(111),char(110),char(84),char(104),char(114),
+char(101),char(115),char(104),char(111),char(108),char(100),char(0),char(109),char(95),char(109),char(105),char(110),char(105),char(109),char(117),char(109),char(83),char(111),char(108),char(118),
+char(101),char(114),char(66),char(97),char(116),char(99),char(104),char(83),char(105),char(122),char(101),char(0),char(109),char(95),char(115),char(112),char(108),char(105),char(116),char(73),
+char(109),char(112),char(117),char(108),char(115),char(101),char(0),char(109),char(95),char(115),char(111),char(108),char(118),char(101),char(114),char(73),char(110),char(102),char(111),char(0),
+char(109),char(95),char(103),char(114),char(97),char(118),char(105),char(116),char(121),char(0),char(109),char(95),char(99),char(111),char(108),char(108),char(105),char(115),char(105),char(111),
+char(110),char(79),char(98),char(106),char(101),char(99),char(116),char(68),char(97),char(116),char(97),char(0),char(109),char(95),char(105),char(110),char(118),char(73),char(110),char(101),
+char(114),char(116),char(105),char(97),char(84),char(101),char(110),char(115),char(111),char(114),char(87),char(111),char(114),char(108),char(100),char(0),char(109),char(95),char(108),char(105),
+char(110),char(101),char(97),char(114),char(86),char(101),char(108),char(111),char(99),char(105),char(116),char(121),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),
+char(97),char(114),char(86),char(101),char(108),char(111),char(99),char(105),char(116),char(121),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),
+char(70),char(97),char(99),char(116),char(111),char(114),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(70),char(97),char(99),char(116),char(111),
+char(114),char(0),char(109),char(95),char(103),char(114),char(97),char(118),char(105),char(116),char(121),char(95),char(97),char(99),char(99),char(101),char(108),char(101),char(114),char(97),
+char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(105),char(110),char(118),char(73),char(110),char(101),char(114),char(116),char(105),char(97),char(76),char(111),char(99),
+char(97),char(108),char(0),char(109),char(95),char(116),char(111),char(116),char(97),char(108),char(70),char(111),char(114),char(99),char(101),char(0),char(109),char(95),char(116),char(111),
+char(116),char(97),char(108),char(84),char(111),char(114),char(113),char(117),char(101),char(0),char(109),char(95),char(105),char(110),char(118),char(101),char(114),char(115),char(101),char(77),
+char(97),char(115),char(115),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(68),char(97),char(109),char(112),char(105),char(110),char(103),char(0),
+char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(68),char(97),char(109),char(112),char(105),char(110),char(103),char(0),char(109),char(95),char(97),
+char(100),char(100),char(105),char(116),char(105),char(111),char(110),char(97),char(108),char(68),char(97),char(109),char(112),char(105),char(110),char(103),char(70),char(97),char(99),char(116),
+char(111),char(114),char(0),char(109),char(95),char(97),char(100),char(100),char(105),char(116),char(105),char(111),char(110),char(97),char(108),char(76),char(105),char(110),char(101),char(97),
+char(114),char(68),char(97),char(109),char(112),char(105),char(110),char(103),char(84),char(104),char(114),char(101),char(115),char(104),char(111),char(108),char(100),char(83),char(113),char(114),
+char(0),char(109),char(95),char(97),char(100),char(100),char(105),char(116),char(105),char(111),char(110),char(97),char(108),char(65),char(110),char(103),char(117),char(108),char(97),char(114),
+char(68),char(97),char(109),char(112),char(105),char(110),char(103),char(84),char(104),char(114),char(101),char(115),char(104),char(111),char(108),char(100),char(83),char(113),char(114),char(0),
+char(109),char(95),char(97),char(100),char(100),char(105),char(116),char(105),char(111),char(110),char(97),char(108),char(65),char(110),char(103),char(117),char(108),char(97),char(114),char(68),
+char(97),char(109),char(112),char(105),char(110),char(103),char(70),char(97),char(99),char(116),char(111),char(114),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),
+char(114),char(83),char(108),char(101),char(101),char(112),char(105),char(110),char(103),char(84),char(104),char(114),char(101),char(115),char(104),char(111),char(108),char(100),char(0),char(109),
+char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(83),char(108),char(101),char(101),char(112),char(105),char(110),char(103),char(84),char(104),char(114),char(101),
+char(115),char(104),char(111),char(108),char(100),char(0),char(109),char(95),char(97),char(100),char(100),char(105),char(116),char(105),char(111),char(110),char(97),char(108),char(68),char(97),
+char(109),char(112),char(105),char(110),char(103),char(0),char(109),char(95),char(110),char(117),char(109),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),
+char(116),char(82),char(111),char(119),char(115),char(0),char(110),char(117),char(98),char(0),char(42),char(109),char(95),char(114),char(98),char(65),char(0),char(42),char(109),char(95),
+char(114),char(98),char(66),char(0),char(109),char(95),char(117),char(115),char(101),char(114),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),
+char(84),char(121),char(112),char(101),char(0),char(109),char(95),char(117),char(115),char(101),char(114),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),
+char(116),char(73),char(100),char(0),char(109),char(95),char(110),char(101),char(101),char(100),char(115),char(70),char(101),char(101),char(100),char(98),char(97),char(99),char(107),char(0),
+char(109),char(95),char(97),char(112),char(112),char(108),char(105),char(101),char(100),char(73),char(109),char(112),char(117),char(108),char(115),char(101),char(0),char(109),char(95),char(100),
+char(98),char(103),char(68),char(114),char(97),char(119),char(83),char(105),char(122),char(101),char(0),char(109),char(95),char(100),char(105),char(115),char(97),char(98),char(108),char(101),
+char(67),char(111),char(108),char(108),char(105),char(115),char(105),char(111),char(110),char(115),char(66),char(101),char(116),char(119),char(101),char(101),char(110),char(76),char(105),char(110),
+char(107),char(101),char(100),char(66),char(111),char(100),char(105),char(101),char(115),char(0),char(109),char(95),char(111),char(118),char(101),char(114),char(114),char(105),char(100),char(101),
+char(78),char(117),char(109),char(83),char(111),char(108),char(118),char(101),char(114),char(73),char(116),char(101),char(114),char(97),char(116),char(105),char(111),char(110),char(115),char(0),
+char(109),char(95),char(98),char(114),char(101),char(97),char(107),char(105),char(110),char(103),char(73),char(109),char(112),char(117),char(108),char(115),char(101),char(84),char(104),char(114),
+char(101),char(115),char(104),char(111),char(108),char(100),char(0),char(109),char(95),char(105),char(115),char(69),char(110),char(97),char(98),char(108),char(101),char(100),char(0),char(112),
+char(97),char(100),char(100),char(105),char(110),char(103),char(91),char(52),char(93),char(0),char(109),char(95),char(116),char(121),char(112),char(101),char(67),char(111),char(110),char(115),
+char(116),char(114),char(97),char(105),char(110),char(116),char(68),char(97),char(116),char(97),char(0),char(109),char(95),char(112),char(105),char(118),char(111),char(116),char(73),char(110),
+char(65),char(0),char(109),char(95),char(112),char(105),char(118),char(111),char(116),char(73),char(110),char(66),char(0),char(109),char(95),char(114),char(98),char(65),char(70),char(114),
+char(97),char(109),char(101),char(0),char(109),char(95),char(114),char(98),char(66),char(70),char(114),char(97),char(109),char(101),char(0),char(109),char(95),char(117),char(115),char(101),
+char(82),char(101),char(102),char(101),char(114),char(101),char(110),char(99),char(101),char(70),char(114),char(97),char(109),char(101),char(65),char(0),char(109),char(95),char(97),char(110),
+char(103),char(117),char(108),char(97),char(114),char(79),char(110),char(108),char(121),char(0),char(109),char(95),char(101),char(110),char(97),char(98),char(108),char(101),char(65),char(110),
+char(103),char(117),char(108),char(97),char(114),char(77),char(111),char(116),char(111),char(114),char(0),char(109),char(95),char(109),char(111),char(116),char(111),char(114),char(84),char(97),
+char(114),char(103),char(101),char(116),char(86),char(101),char(108),char(111),char(99),char(105),char(116),char(121),char(0),char(109),char(95),char(109),char(97),char(120),char(77),char(111),
+char(116),char(111),char(114),char(73),char(109),char(112),char(117),char(108),char(115),char(101),char(0),char(109),char(95),char(108),char(111),char(119),char(101),char(114),char(76),char(105),
+char(109),char(105),char(116),char(0),char(109),char(95),char(117),char(112),char(112),char(101),char(114),char(76),char(105),char(109),char(105),char(116),char(0),char(109),char(95),char(108),
+char(105),char(109),char(105),char(116),char(83),char(111),char(102),char(116),char(110),char(101),char(115),char(115),char(0),char(109),char(95),char(98),char(105),char(97),char(115),char(70),
+char(97),char(99),char(116),char(111),char(114),char(0),char(109),char(95),char(114),char(101),char(108),char(97),char(120),char(97),char(116),char(105),char(111),char(110),char(70),char(97),
+char(99),char(116),char(111),char(114),char(0),char(109),char(95),char(112),char(97),char(100),char(100),char(105),char(110),char(103),char(49),char(91),char(52),char(93),char(0),char(109),
+char(95),char(115),char(119),char(105),char(110),char(103),char(83),char(112),char(97),char(110),char(49),char(0),char(109),char(95),char(115),char(119),char(105),char(110),char(103),char(83),
+char(112),char(97),char(110),char(50),char(0),char(109),char(95),char(116),char(119),char(105),char(115),char(116),char(83),char(112),char(97),char(110),char(0),char(109),char(95),char(108),
+char(105),char(110),char(101),char(97),char(114),char(85),char(112),char(112),char(101),char(114),char(76),char(105),char(109),char(105),char(116),char(0),char(109),char(95),char(108),char(105),
+char(110),char(101),char(97),char(114),char(76),char(111),char(119),char(101),char(114),char(76),char(105),char(109),char(105),char(116),char(0),char(109),char(95),char(97),char(110),char(103),
+char(117),char(108),char(97),char(114),char(85),char(112),char(112),char(101),char(114),char(76),char(105),char(109),char(105),char(116),char(0),char(109),char(95),char(97),char(110),char(103),
+char(117),char(108),char(97),char(114),char(76),char(111),char(119),char(101),char(114),char(76),char(105),char(109),char(105),char(116),char(0),char(109),char(95),char(117),char(115),char(101),
+char(76),char(105),char(110),char(101),char(97),char(114),char(82),char(101),char(102),char(101),char(114),char(101),char(110),char(99),char(101),char(70),char(114),char(97),char(109),char(101),
+char(65),char(0),char(109),char(95),char(117),char(115),char(101),char(79),char(102),char(102),char(115),char(101),char(116),char(70),char(111),char(114),char(67),char(111),char(110),char(115),
+char(116),char(114),char(97),char(105),char(110),char(116),char(70),char(114),char(97),char(109),char(101),char(0),char(109),char(95),char(54),char(100),char(111),char(102),char(68),char(97),
+char(116),char(97),char(0),char(109),char(95),char(115),char(112),char(114),char(105),char(110),char(103),char(69),char(110),char(97),char(98),char(108),char(101),char(100),char(91),char(54),
+char(93),char(0),char(109),char(95),char(101),char(113),char(117),char(105),char(108),char(105),char(98),char(114),char(105),char(117),char(109),char(80),char(111),char(105),char(110),char(116),
+char(91),char(54),char(93),char(0),char(109),char(95),char(115),char(112),char(114),char(105),char(110),char(103),char(83),char(116),char(105),char(102),char(102),char(110),char(101),char(115),
+char(115),char(91),char(54),char(93),char(0),char(109),char(95),char(115),char(112),char(114),char(105),char(110),char(103),char(68),char(97),char(109),char(112),char(105),char(110),char(103),
+char(91),char(54),char(93),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(66),char(111),char(117),char(110),char(99),char(101),char(0),char(109),
+char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(83),char(116),char(111),char(112),char(69),char(82),char(80),char(0),char(109),char(95),char(108),char(105),char(110),
+char(101),char(97),char(114),char(83),char(116),char(111),char(112),char(67),char(70),char(77),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(77),
+char(111),char(116),char(111),char(114),char(69),char(82),char(80),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(77),char(111),char(116),char(111),
+char(114),char(67),char(70),char(77),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(84),char(97),char(114),char(103),char(101),char(116),char(86),
+char(101),char(108),char(111),char(99),char(105),char(116),char(121),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(77),char(97),char(120),char(77),
+char(111),char(116),char(111),char(114),char(70),char(111),char(114),char(99),char(101),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(83),char(101),
+char(114),char(118),char(111),char(84),char(97),char(114),char(103),char(101),char(116),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(83),char(112),
+char(114),char(105),char(110),char(103),char(83),char(116),char(105),char(102),char(102),char(110),char(101),char(115),char(115),char(0),char(109),char(95),char(108),char(105),char(110),char(101),
+char(97),char(114),char(83),char(112),char(114),char(105),char(110),char(103),char(68),char(97),char(109),char(112),char(105),char(110),char(103),char(0),char(109),char(95),char(108),char(105),
+char(110),char(101),char(97),char(114),char(69),char(113),char(117),char(105),char(108),char(105),char(98),char(114),char(105),char(117),char(109),char(80),char(111),char(105),char(110),char(116),
+char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(69),char(110),char(97),char(98),char(108),char(101),char(77),char(111),char(116),char(111),char(114),
+char(91),char(52),char(93),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(83),char(101),char(114),char(118),char(111),char(77),char(111),char(116),
+char(111),char(114),char(91),char(52),char(93),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(69),char(110),char(97),char(98),char(108),char(101),
+char(83),char(112),char(114),char(105),char(110),char(103),char(91),char(52),char(93),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(83),char(112),
+char(114),char(105),char(110),char(103),char(83),char(116),char(105),char(102),char(102),char(110),char(101),char(115),char(115),char(76),char(105),char(109),char(105),char(116),char(101),char(100),
+char(91),char(52),char(93),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(83),char(112),char(114),char(105),char(110),char(103),char(68),char(97),
+char(109),char(112),char(105),char(110),char(103),char(76),char(105),char(109),char(105),char(116),char(101),char(100),char(91),char(52),char(93),char(0),char(109),char(95),char(97),char(110),
+char(103),char(117),char(108),char(97),char(114),char(66),char(111),char(117),char(110),char(99),char(101),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),
+char(114),char(83),char(116),char(111),char(112),char(69),char(82),char(80),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(83),char(116),
+char(111),char(112),char(67),char(70),char(77),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(77),char(111),char(116),char(111),char(114),
+char(69),char(82),char(80),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(77),char(111),char(116),char(111),char(114),char(67),char(70),
+char(77),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(84),char(97),char(114),char(103),char(101),char(116),char(86),char(101),char(108),
+char(111),char(99),char(105),char(116),char(121),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(77),char(97),char(120),char(77),char(111),
+char(116),char(111),char(114),char(70),char(111),char(114),char(99),char(101),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(83),char(101),
+char(114),char(118),char(111),char(84),char(97),char(114),char(103),char(101),char(116),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(83),
+char(112),char(114),char(105),char(110),char(103),char(83),char(116),char(105),char(102),char(102),char(110),char(101),char(115),char(115),char(0),char(109),char(95),char(97),char(110),char(103),
+char(117),char(108),char(97),char(114),char(83),char(112),char(114),char(105),char(110),char(103),char(68),char(97),char(109),char(112),char(105),char(110),char(103),char(0),char(109),char(95),
+char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(69),char(113),char(117),char(105),char(108),char(105),char(98),char(114),char(105),char(117),char(109),char(80),char(111),
+char(105),char(110),char(116),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(69),char(110),char(97),char(98),char(108),char(101),char(77),
+char(111),char(116),char(111),char(114),char(91),char(52),char(93),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(83),char(101),char(114),
+char(118),char(111),char(77),char(111),char(116),char(111),char(114),char(91),char(52),char(93),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),
+char(69),char(110),char(97),char(98),char(108),char(101),char(83),char(112),char(114),char(105),char(110),char(103),char(91),char(52),char(93),char(0),char(109),char(95),char(97),char(110),
+char(103),char(117),char(108),char(97),char(114),char(83),char(112),char(114),char(105),char(110),char(103),char(83),char(116),char(105),char(102),char(102),char(110),char(101),char(115),char(115),
+char(76),char(105),char(109),char(105),char(116),char(101),char(100),char(91),char(52),char(93),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),
+char(83),char(112),char(114),char(105),char(110),char(103),char(68),char(97),char(109),char(112),char(105),char(110),char(103),char(76),char(105),char(109),char(105),char(116),char(101),char(100),
+char(91),char(52),char(93),char(0),char(109),char(95),char(114),char(111),char(116),char(97),char(116),char(101),char(79),char(114),char(100),char(101),char(114),char(0),char(109),char(95),
+char(97),char(120),char(105),char(115),char(73),char(110),char(65),char(0),char(109),char(95),char(97),char(120),char(105),char(115),char(73),char(110),char(66),char(0),char(109),char(95),
+char(114),char(97),char(116),char(105),char(111),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(83),char(116),char(105),char(102),char(102),char(110),
+char(101),char(115),char(115),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(83),char(116),char(105),char(102),char(102),char(110),char(101),
+char(115),char(115),char(0),char(109),char(95),char(118),char(111),char(108),char(117),char(109),char(101),char(83),char(116),char(105),char(102),char(102),char(110),char(101),char(115),char(115),
+char(0),char(42),char(109),char(95),char(109),char(97),char(116),char(101),char(114),char(105),char(97),char(108),char(0),char(109),char(95),char(112),char(111),char(115),char(105),char(116),
+char(105),char(111),char(110),char(0),char(109),char(95),char(112),char(114),char(101),char(118),char(105),char(111),char(117),char(115),char(80),char(111),char(115),char(105),char(116),char(105),
+char(111),char(110),char(0),char(109),char(95),char(118),char(101),char(108),char(111),char(99),char(105),char(116),char(121),char(0),char(109),char(95),char(97),char(99),char(99),char(117),
+char(109),char(117),char(108),char(97),char(116),char(101),char(100),char(70),char(111),char(114),char(99),char(101),char(0),char(109),char(95),char(110),char(111),char(114),char(109),char(97),
+char(108),char(0),char(109),char(95),char(97),char(114),char(101),char(97),char(0),char(109),char(95),char(97),char(116),char(116),char(97),char(99),char(104),char(0),char(109),char(95),
+char(110),char(111),char(100),char(101),char(73),char(110),char(100),char(105),char(99),char(101),char(115),char(91),char(50),char(93),char(0),char(109),char(95),char(114),char(101),char(115),
+char(116),char(76),char(101),char(110),char(103),char(116),char(104),char(0),char(109),char(95),char(98),char(98),char(101),char(110),char(100),char(105),char(110),char(103),char(0),char(109),
+char(95),char(110),char(111),char(100),char(101),char(73),char(110),char(100),char(105),char(99),char(101),char(115),char(91),char(51),char(93),char(0),char(109),char(95),char(114),char(101),
+char(115),char(116),char(65),char(114),char(101),char(97),char(0),char(109),char(95),char(99),char(48),char(91),char(52),char(93),char(0),char(109),char(95),char(110),char(111),char(100),
+char(101),char(73),char(110),char(100),char(105),char(99),char(101),char(115),char(91),char(52),char(93),char(0),char(109),char(95),char(114),char(101),char(115),char(116),char(86),char(111),
+char(108),char(117),char(109),char(101),char(0),char(109),char(95),char(99),char(49),char(0),char(109),char(95),char(99),char(50),char(0),char(109),char(95),char(99),char(48),char(0),
+char(109),char(95),char(108),char(111),char(99),char(97),char(108),char(70),char(114),char(97),char(109),char(101),char(0),char(42),char(109),char(95),char(114),char(105),char(103),char(105),
+char(100),char(66),char(111),char(100),char(121),char(0),char(109),char(95),char(110),char(111),char(100),char(101),char(73),char(110),char(100),char(101),char(120),char(0),char(109),char(95),
+char(97),char(101),char(114),char(111),char(77),char(111),char(100),char(101),char(108),char(0),char(109),char(95),char(98),char(97),char(117),char(109),char(103),char(97),char(114),char(116),
+char(101),char(0),char(109),char(95),char(100),char(114),char(97),char(103),char(0),char(109),char(95),char(108),char(105),char(102),char(116),char(0),char(109),char(95),char(112),char(114),
+char(101),char(115),char(115),char(117),char(114),char(101),char(0),char(109),char(95),char(118),char(111),char(108),char(117),char(109),char(101),char(0),char(109),char(95),char(100),char(121),
+char(110),char(97),char(109),char(105),char(99),char(70),char(114),char(105),char(99),char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(112),char(111),char(115),char(101),
+char(77),char(97),char(116),char(99),char(104),char(0),char(109),char(95),char(114),char(105),char(103),char(105),char(100),char(67),char(111),char(110),char(116),char(97),char(99),char(116),
+char(72),char(97),char(114),char(100),char(110),char(101),char(115),char(115),char(0),char(109),char(95),char(107),char(105),char(110),char(101),char(116),char(105),char(99),char(67),char(111),
+char(110),char(116),char(97),char(99),char(116),char(72),char(97),char(114),char(100),char(110),char(101),char(115),char(115),char(0),char(109),char(95),char(115),char(111),char(102),char(116),
+char(67),char(111),char(110),char(116),char(97),char(99),char(116),char(72),char(97),char(114),char(100),char(110),char(101),char(115),char(115),char(0),char(109),char(95),char(97),char(110),
+char(99),char(104),char(111),char(114),char(72),char(97),char(114),char(100),char(110),char(101),char(115),char(115),char(0),char(109),char(95),char(115),char(111),char(102),char(116),char(82),
+char(105),char(103),char(105),char(100),char(67),char(108),char(117),char(115),char(116),char(101),char(114),char(72),char(97),char(114),char(100),char(110),char(101),char(115),char(115),char(0),
+char(109),char(95),char(115),char(111),char(102),char(116),char(75),char(105),char(110),char(101),char(116),char(105),char(99),char(67),char(108),char(117),char(115),char(116),char(101),char(114),
+char(72),char(97),char(114),char(100),char(110),char(101),char(115),char(115),char(0),char(109),char(95),char(115),char(111),char(102),char(116),char(83),char(111),char(102),char(116),char(67),
+char(108),char(117),char(115),char(116),char(101),char(114),char(72),char(97),char(114),char(100),char(110),char(101),char(115),char(115),char(0),char(109),char(95),char(115),char(111),char(102),
+char(116),char(82),char(105),char(103),char(105),char(100),char(67),char(108),char(117),char(115),char(116),char(101),char(114),char(73),char(109),char(112),char(117),char(108),char(115),char(101),
+char(83),char(112),char(108),char(105),char(116),char(0),char(109),char(95),char(115),char(111),char(102),char(116),char(75),char(105),char(110),char(101),char(116),char(105),char(99),char(67),
+char(108),char(117),char(115),char(116),char(101),char(114),char(73),char(109),char(112),char(117),char(108),char(115),char(101),char(83),char(112),char(108),char(105),char(116),char(0),char(109),
+char(95),char(115),char(111),char(102),char(116),char(83),char(111),char(102),char(116),char(67),char(108),char(117),char(115),char(116),char(101),char(114),char(73),char(109),char(112),char(117),
+char(108),char(115),char(101),char(83),char(112),char(108),char(105),char(116),char(0),char(109),char(95),char(109),char(97),char(120),char(86),char(111),char(108),char(117),char(109),char(101),
+char(0),char(109),char(95),char(116),char(105),char(109),char(101),char(83),char(99),char(97),char(108),char(101),char(0),char(109),char(95),char(118),char(101),char(108),char(111),char(99),
+char(105),char(116),char(121),char(73),char(116),char(101),char(114),char(97),char(116),char(105),char(111),char(110),char(115),char(0),char(109),char(95),char(112),char(111),char(115),char(105),
+char(116),char(105),char(111),char(110),char(73),char(116),char(101),char(114),char(97),char(116),char(105),char(111),char(110),char(115),char(0),char(109),char(95),char(100),char(114),char(105),
+char(102),char(116),char(73),char(116),char(101),char(114),char(97),char(116),char(105),char(111),char(110),char(115),char(0),char(109),char(95),char(99),char(108),char(117),char(115),char(116),
+char(101),char(114),char(73),char(116),char(101),char(114),char(97),char(116),char(105),char(111),char(110),char(115),char(0),char(109),char(95),char(114),char(111),char(116),char(0),char(109),
+char(95),char(115),char(99),char(97),char(108),char(101),char(0),char(109),char(95),char(97),char(113),char(113),char(0),char(109),char(95),char(99),char(111),char(109),char(0),char(42),
+char(109),char(95),char(112),char(111),char(115),char(105),char(116),char(105),char(111),char(110),char(115),char(0),char(42),char(109),char(95),char(119),char(101),char(105),char(103),char(104),
+char(116),char(115),char(0),char(109),char(95),char(110),char(117),char(109),char(80),char(111),char(115),char(105),char(116),char(105),char(111),char(110),char(115),char(0),char(109),char(95),
+char(110),char(117),char(109),char(87),char(101),char(105),char(103),char(116),char(115),char(0),char(109),char(95),char(98),char(118),char(111),char(108),char(117),char(109),char(101),char(0),
+char(109),char(95),char(98),char(102),char(114),char(97),char(109),char(101),char(0),char(109),char(95),char(102),char(114),char(97),char(109),char(101),char(120),char(102),char(111),char(114),
+char(109),char(0),char(109),char(95),char(108),char(111),char(99),char(105),char(105),char(0),char(109),char(95),char(105),char(110),char(118),char(119),char(105),char(0),char(109),char(95),
+char(118),char(105),char(109),char(112),char(117),char(108),char(115),char(101),char(115),char(91),char(50),char(93),char(0),char(109),char(95),char(100),char(105),char(109),char(112),char(117),
+char(108),char(115),char(101),char(115),char(91),char(50),char(93),char(0),char(109),char(95),char(108),char(118),char(0),char(109),char(95),char(97),char(118),char(0),char(42),char(109),
+char(95),char(102),char(114),char(97),char(109),char(101),char(114),char(101),char(102),char(115),char(0),char(42),char(109),char(95),char(110),char(111),char(100),char(101),char(73),char(110),
+char(100),char(105),char(99),char(101),char(115),char(0),char(42),char(109),char(95),char(109),char(97),char(115),char(115),char(101),char(115),char(0),char(109),char(95),char(110),char(117),
+char(109),char(70),char(114),char(97),char(109),char(101),char(82),char(101),char(102),char(115),char(0),char(109),char(95),char(110),char(117),char(109),char(78),char(111),char(100),char(101),
+char(115),char(0),char(109),char(95),char(110),char(117),char(109),char(77),char(97),char(115),char(115),char(101),char(115),char(0),char(109),char(95),char(105),char(100),char(109),char(97),
+char(115),char(115),char(0),char(109),char(95),char(105),char(109),char(97),char(115),char(115),char(0),char(109),char(95),char(110),char(118),char(105),char(109),char(112),char(117),char(108),
+char(115),char(101),char(115),char(0),char(109),char(95),char(110),char(100),char(105),char(109),char(112),char(117),char(108),char(115),char(101),char(115),char(0),char(109),char(95),char(110),
+char(100),char(97),char(109),char(112),char(105),char(110),char(103),char(0),char(109),char(95),char(108),char(100),char(97),char(109),char(112),char(105),char(110),char(103),char(0),char(109),
+char(95),char(97),char(100),char(97),char(109),char(112),char(105),char(110),char(103),char(0),char(109),char(95),char(109),char(97),char(116),char(99),char(104),char(105),char(110),char(103),
+char(0),char(109),char(95),char(109),char(97),char(120),char(83),char(101),char(108),char(102),char(67),char(111),char(108),char(108),char(105),char(115),char(105),char(111),char(110),char(73),
+char(109),char(112),char(117),char(108),char(115),char(101),char(0),char(109),char(95),char(115),char(101),char(108),char(102),char(67),char(111),char(108),char(108),char(105),char(115),char(105),
+char(111),char(110),char(73),char(109),char(112),char(117),char(108),char(115),char(101),char(70),char(97),char(99),char(116),char(111),char(114),char(0),char(109),char(95),char(99),char(111),
+char(110),char(116),char(97),char(105),char(110),char(115),char(65),char(110),char(99),char(104),char(111),char(114),char(0),char(109),char(95),char(99),char(111),char(108),char(108),char(105),
+char(100),char(101),char(0),char(109),char(95),char(99),char(108),char(117),char(115),char(116),char(101),char(114),char(73),char(110),char(100),char(101),char(120),char(0),char(42),char(109),
+char(95),char(98),char(111),char(100),char(121),char(65),char(0),char(42),char(109),char(95),char(98),char(111),char(100),char(121),char(66),char(0),char(109),char(95),char(114),char(101),
+char(102),char(115),char(91),char(50),char(93),char(0),char(109),char(95),char(99),char(102),char(109),char(0),char(109),char(95),char(115),char(112),char(108),char(105),char(116),char(0),
+char(109),char(95),char(100),char(101),char(108),char(101),char(116),char(101),char(0),char(109),char(95),char(114),char(101),char(108),char(80),char(111),char(115),char(105),char(116),char(105),
+char(111),char(110),char(91),char(50),char(93),char(0),char(109),char(95),char(98),char(111),char(100),char(121),char(65),char(116),char(121),char(112),char(101),char(0),char(109),char(95),
+char(98),char(111),char(100),char(121),char(66),char(116),char(121),char(112),char(101),char(0),char(109),char(95),char(106),char(111),char(105),char(110),char(116),char(84),char(121),char(112),
+char(101),char(0),char(42),char(109),char(95),char(112),char(111),char(115),char(101),char(0),char(42),char(42),char(109),char(95),char(109),char(97),char(116),char(101),char(114),char(105),
+char(97),char(108),char(115),char(0),char(42),char(109),char(95),char(110),char(111),char(100),char(101),char(115),char(0),char(42),char(109),char(95),char(108),char(105),char(110),char(107),
+char(115),char(0),char(42),char(109),char(95),char(102),char(97),char(99),char(101),char(115),char(0),char(42),char(109),char(95),char(116),char(101),char(116),char(114),char(97),char(104),
+char(101),char(100),char(114),char(97),char(0),char(42),char(109),char(95),char(97),char(110),char(99),char(104),char(111),char(114),char(115),char(0),char(42),char(109),char(95),char(99),
+char(108),char(117),char(115),char(116),char(101),char(114),char(115),char(0),char(42),char(109),char(95),char(106),char(111),char(105),char(110),char(116),char(115),char(0),char(109),char(95),
+char(110),char(117),char(109),char(77),char(97),char(116),char(101),char(114),char(105),char(97),char(108),char(115),char(0),char(109),char(95),char(110),char(117),char(109),char(76),char(105),
+char(110),char(107),char(115),char(0),char(109),char(95),char(110),char(117),char(109),char(70),char(97),char(99),char(101),char(115),char(0),char(109),char(95),char(110),char(117),char(109),
+char(84),char(101),char(116),char(114),char(97),char(104),char(101),char(100),char(114),char(97),char(0),char(109),char(95),char(110),char(117),char(109),char(65),char(110),char(99),char(104),
+char(111),char(114),char(115),char(0),char(109),char(95),char(110),char(117),char(109),char(67),char(108),char(117),char(115),char(116),char(101),char(114),char(115),char(0),char(109),char(95),
+char(110),char(117),char(109),char(74),char(111),char(105),char(110),char(116),char(115),char(0),char(109),char(95),char(99),char(111),char(110),char(102),char(105),char(103),char(0),char(109),
+char(95),char(122),char(101),char(114),char(111),char(82),char(111),char(116),char(80),char(97),char(114),char(101),char(110),char(116),char(84),char(111),char(84),char(104),char(105),char(115),
+char(0),char(109),char(95),char(112),char(97),char(114),char(101),char(110),char(116),char(67),char(111),char(109),char(84),char(111),char(84),char(104),char(105),char(115),char(80),char(105),
+char(118),char(111),char(116),char(79),char(102),char(102),char(115),char(101),char(116),char(0),char(109),char(95),char(116),char(104),char(105),char(115),char(80),char(105),char(118),char(111),
+char(116),char(84),char(111),char(84),char(104),char(105),char(115),char(67),char(111),char(109),char(79),char(102),char(102),char(115),char(101),char(116),char(0),char(109),char(95),char(106),
+char(111),char(105),char(110),char(116),char(65),char(120),char(105),char(115),char(84),char(111),char(112),char(91),char(54),char(93),char(0),char(109),char(95),char(106),char(111),char(105),
+char(110),char(116),char(65),char(120),char(105),char(115),char(66),char(111),char(116),char(116),char(111),char(109),char(91),char(54),char(93),char(0),char(109),char(95),char(108),char(105),
+char(110),char(107),char(73),char(110),char(101),char(114),char(116),char(105),char(97),char(0),char(109),char(95),char(97),char(98),char(115),char(70),char(114),char(97),char(109),char(101),
+char(84),char(111),char(116),char(86),char(101),char(108),char(111),char(99),char(105),char(116),char(121),char(84),char(111),char(112),char(0),char(109),char(95),char(97),char(98),char(115),
+char(70),char(114),char(97),char(109),char(101),char(84),char(111),char(116),char(86),char(101),char(108),char(111),char(99),char(105),char(116),char(121),char(66),char(111),char(116),char(116),
+char(111),char(109),char(0),char(109),char(95),char(97),char(98),char(115),char(70),char(114),char(97),char(109),char(101),char(76),char(111),char(99),char(86),char(101),char(108),char(111),
+char(99),char(105),char(116),char(121),char(84),char(111),char(112),char(0),char(109),char(95),char(97),char(98),char(115),char(70),char(114),char(97),char(109),char(101),char(76),char(111),
+char(99),char(86),char(101),char(108),char(111),char(99),char(105),char(116),char(121),char(66),char(111),char(116),char(116),char(111),char(109),char(0),char(109),char(95),char(108),char(105),
+char(110),char(107),char(77),char(97),char(115),char(115),char(0),char(109),char(95),char(112),char(97),char(114),char(101),char(110),char(116),char(73),char(110),char(100),char(101),char(120),
+char(0),char(109),char(95),char(100),char(111),char(102),char(67),char(111),char(117),char(110),char(116),char(0),char(109),char(95),char(112),char(111),char(115),char(86),char(97),char(114),
+char(67),char(111),char(117),char(110),char(116),char(0),char(109),char(95),char(106),char(111),char(105),char(110),char(116),char(80),char(111),char(115),char(91),char(55),char(93),char(0),
+char(109),char(95),char(106),char(111),char(105),char(110),char(116),char(86),char(101),char(108),char(91),char(54),char(93),char(0),char(109),char(95),char(106),char(111),char(105),char(110),
+char(116),char(84),char(111),char(114),char(113),char(117),char(101),char(91),char(54),char(93),char(0),char(109),char(95),char(106),char(111),char(105),char(110),char(116),char(68),char(97),
+char(109),char(112),char(105),char(110),char(103),char(0),char(109),char(95),char(106),char(111),char(105),char(110),char(116),char(70),char(114),char(105),char(99),char(116),char(105),char(111),
+char(110),char(0),char(109),char(95),char(106),char(111),char(105),char(110),char(116),char(76),char(111),char(119),char(101),char(114),char(76),char(105),char(109),char(105),char(116),char(0),
+char(109),char(95),char(106),char(111),char(105),char(110),char(116),char(85),char(112),char(112),char(101),char(114),char(76),char(105),char(109),char(105),char(116),char(0),char(109),char(95),
+char(106),char(111),char(105),char(110),char(116),char(77),char(97),char(120),char(70),char(111),char(114),char(99),char(101),char(0),char(109),char(95),char(106),char(111),char(105),char(110),
+char(116),char(77),char(97),char(120),char(86),char(101),char(108),char(111),char(99),char(105),char(116),char(121),char(0),char(42),char(109),char(95),char(108),char(105),char(110),char(107),
+char(78),char(97),char(109),char(101),char(0),char(42),char(109),char(95),char(106),char(111),char(105),char(110),char(116),char(78),char(97),char(109),char(101),char(0),char(42),char(109),
+char(95),char(108),char(105),char(110),char(107),char(67),char(111),char(108),char(108),char(105),char(100),char(101),char(114),char(0),char(42),char(109),char(95),char(112),char(97),char(100),
+char(100),char(105),char(110),char(103),char(80),char(116),char(114),char(0),char(109),char(95),char(98),char(97),char(115),char(101),char(87),char(111),char(114),char(108),char(100),char(80),
+char(111),char(115),char(105),char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(98),char(97),char(115),char(101),char(87),char(111),char(114),char(108),char(100),char(79),
+char(114),char(105),char(101),char(110),char(116),char(97),char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(98),char(97),char(115),char(101),char(76),char(105),char(110),
+char(101),char(97),char(114),char(86),char(101),char(108),char(111),char(99),char(105),char(116),char(121),char(0),char(109),char(95),char(98),char(97),char(115),char(101),char(65),char(110),
+char(103),char(117),char(108),char(97),char(114),char(86),char(101),char(108),char(111),char(99),char(105),char(116),char(121),char(0),char(109),char(95),char(98),char(97),char(115),char(101),
+char(73),char(110),char(101),char(114),char(116),char(105),char(97),char(0),char(109),char(95),char(98),char(97),char(115),char(101),char(77),char(97),char(115),char(115),char(0),char(42),
+char(109),char(95),char(98),char(97),char(115),char(101),char(78),char(97),char(109),char(101),char(0),char(42),char(109),char(95),char(98),char(97),char(115),char(101),char(67),char(111),
+char(108),char(108),char(105),char(100),char(101),char(114),char(0),char(109),char(95),char(99),char(111),char(108),char(79),char(98),char(106),char(68),char(97),char(116),char(97),char(0),
+char(42),char(109),char(95),char(109),char(117),char(108),char(116),char(105),char(66),char(111),char(100),char(121),char(0),char(109),char(95),char(108),char(105),char(110),char(107),char(0),
+char(84),char(89),char(80),char(69),char(99),char(0),char(0),char(0),char(99),char(104),char(97),char(114),char(0),char(117),char(99),char(104),char(97),char(114),char(0),char(115),
+char(104),char(111),char(114),char(116),char(0),char(117),char(115),char(104),char(111),char(114),char(116),char(0),char(105),char(110),char(116),char(0),char(108),char(111),char(110),char(103),
+char(0),char(117),char(108),char(111),char(110),char(103),char(0),char(102),char(108),char(111),char(97),char(116),char(0),char(100),char(111),char(117),char(98),char(108),char(101),char(0),
+char(118),char(111),char(105),char(100),char(0),char(80),char(111),char(105),char(110),char(116),char(101),char(114),char(65),char(114),char(114),char(97),char(121),char(0),char(98),char(116),
+char(80),char(104),char(121),char(115),char(105),char(99),char(115),char(83),char(121),char(115),char(116),char(101),char(109),char(0),char(76),char(105),char(115),char(116),char(66),char(97),
+char(115),char(101),char(0),char(98),char(116),char(86),char(101),char(99),char(116),char(111),char(114),char(51),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),
+char(97),char(0),char(98),char(116),char(86),char(101),char(99),char(116),char(111),char(114),char(51),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),
+char(97),char(0),char(98),char(116),char(81),char(117),char(97),char(116),char(101),char(114),char(110),char(105),char(111),char(110),char(70),char(108),char(111),char(97),char(116),char(68),
+char(97),char(116),char(97),char(0),char(98),char(116),char(81),char(117),char(97),char(116),char(101),char(114),char(110),char(105),char(111),char(110),char(68),char(111),char(117),char(98),
+char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(77),char(97),char(116),char(114),char(105),char(120),char(51),char(120),char(51),char(70),char(108),
+char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(77),char(97),char(116),char(114),char(105),char(120),char(51),char(120),char(51),char(68),
+char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(84),char(114),char(97),char(110),char(115),char(102),char(111),char(114),
+char(109),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(84),char(114),char(97),char(110),char(115),char(102),char(111),
+char(114),char(109),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(66),char(118),char(104),char(83),char(117),
+char(98),char(116),char(114),char(101),char(101),char(73),char(110),char(102),char(111),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(79),char(112),char(116),char(105),
+char(109),char(105),char(122),char(101),char(100),char(66),char(118),char(104),char(78),char(111),char(100),char(101),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),
char(97),char(0),char(98),char(116),char(79),char(112),char(116),char(105),char(109),char(105),char(122),char(101),char(100),char(66),char(118),char(104),char(78),char(111),char(100),char(101),
-char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(79),char(112),char(116),char(105),char(109),char(105),char(122),char(101),
-char(100),char(66),char(118),char(104),char(78),char(111),char(100),char(101),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),
-char(116),char(81),char(117),char(97),char(110),char(116),char(105),char(122),char(101),char(100),char(66),char(118),char(104),char(78),char(111),char(100),char(101),char(68),char(97),char(116),
-char(97),char(0),char(98),char(116),char(81),char(117),char(97),char(110),char(116),char(105),char(122),char(101),char(100),char(66),char(118),char(104),char(70),char(108),char(111),char(97),
-char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(81),char(117),char(97),char(110),char(116),char(105),char(122),char(101),char(100),char(66),char(118),char(104),
-char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(111),char(108),char(108),char(105),char(115),char(105),
-char(111),char(110),char(83),char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(83),char(116),char(97),char(116),char(105),char(99),
-char(80),char(108),char(97),char(110),char(101),char(83),char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(111),char(110),
-char(118),char(101),char(120),char(73),char(110),char(116),char(101),char(114),char(110),char(97),char(108),char(83),char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97),
-char(0),char(98),char(116),char(80),char(111),char(115),char(105),char(116),char(105),char(111),char(110),char(65),char(110),char(100),char(82),char(97),char(100),char(105),char(117),char(115),
-char(0),char(98),char(116),char(77),char(117),char(108),char(116),char(105),char(83),char(112),char(104),char(101),char(114),char(101),char(83),char(104),char(97),char(112),char(101),char(68),
-char(97),char(116),char(97),char(0),char(98),char(116),char(73),char(110),char(116),char(73),char(110),char(100),char(101),char(120),char(68),char(97),char(116),char(97),char(0),char(98),
-char(116),char(83),char(104),char(111),char(114),char(116),char(73),char(110),char(116),char(73),char(110),char(100),char(101),char(120),char(68),char(97),char(116),char(97),char(0),char(98),
-char(116),char(83),char(104),char(111),char(114),char(116),char(73),char(110),char(116),char(73),char(110),char(100),char(101),char(120),char(84),char(114),char(105),char(112),char(108),char(101),
-char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(104),char(97),char(114),char(73),char(110),char(100),char(101),char(120),char(84),char(114),char(105),
-char(112),char(108),char(101),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(77),char(101),char(115),char(104),char(80),char(97),char(114),char(116),char(68),
-char(97),char(116),char(97),char(0),char(98),char(116),char(83),char(116),char(114),char(105),char(100),char(105),char(110),char(103),char(77),char(101),char(115),char(104),char(73),char(110),
-char(116),char(101),char(114),char(102),char(97),char(99),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(84),char(114),char(105),char(97),char(110),char(103),
-char(108),char(101),char(77),char(101),char(115),char(104),char(83),char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(84),char(114),
-char(105),char(97),char(110),char(103),char(108),char(101),char(73),char(110),char(102),char(111),char(77),char(97),char(112),char(68),char(97),char(116),char(97),char(0),char(98),char(116),
-char(83),char(99),char(97),char(108),char(101),char(100),char(84),char(114),char(105),char(97),char(110),char(103),char(108),char(101),char(77),char(101),char(115),char(104),char(83),char(104),
-char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(111),char(109),char(112),char(111),char(117),char(110),char(100),char(83),char(104),
-char(97),char(112),char(101),char(67),char(104),char(105),char(108),char(100),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(111),char(109),char(112),char(111),
-char(117),char(110),char(100),char(83),char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(121),char(108),char(105),char(110),
-char(100),char(101),char(114),char(83),char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(111),char(110),char(101),char(83),
-char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(97),char(112),char(115),char(117),char(108),char(101),char(83),char(104),
+char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(81),char(117),char(97),char(110),char(116),char(105),char(122),
+char(101),char(100),char(66),char(118),char(104),char(78),char(111),char(100),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(81),char(117),char(97),char(110),
+char(116),char(105),char(122),char(101),char(100),char(66),char(118),char(104),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),
+char(81),char(117),char(97),char(110),char(116),char(105),char(122),char(101),char(100),char(66),char(118),char(104),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),
+char(116),char(97),char(0),char(98),char(116),char(67),char(111),char(108),char(108),char(105),char(115),char(105),char(111),char(110),char(83),char(104),char(97),char(112),char(101),char(68),
+char(97),char(116),char(97),char(0),char(98),char(116),char(83),char(116),char(97),char(116),char(105),char(99),char(80),char(108),char(97),char(110),char(101),char(83),char(104),char(97),
+char(112),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(111),char(110),char(118),char(101),char(120),char(73),char(110),char(116),char(101),char(114),
+char(110),char(97),char(108),char(83),char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(80),char(111),char(115),char(105),char(116),
+char(105),char(111),char(110),char(65),char(110),char(100),char(82),char(97),char(100),char(105),char(117),char(115),char(0),char(98),char(116),char(77),char(117),char(108),char(116),char(105),
+char(83),char(112),char(104),char(101),char(114),char(101),char(83),char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(73),char(110),
+char(116),char(73),char(110),char(100),char(101),char(120),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(83),char(104),char(111),char(114),char(116),char(73),char(110),
+char(116),char(73),char(110),char(100),char(101),char(120),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(83),char(104),char(111),char(114),char(116),char(73),char(110),
+char(116),char(73),char(110),char(100),char(101),char(120),char(84),char(114),char(105),char(112),char(108),char(101),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),
+char(67),char(104),char(97),char(114),char(73),char(110),char(100),char(101),char(120),char(84),char(114),char(105),char(112),char(108),char(101),char(116),char(68),char(97),char(116),char(97),
+char(0),char(98),char(116),char(77),char(101),char(115),char(104),char(80),char(97),char(114),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(83),char(116),
+char(114),char(105),char(100),char(105),char(110),char(103),char(77),char(101),char(115),char(104),char(73),char(110),char(116),char(101),char(114),char(102),char(97),char(99),char(101),char(68),
+char(97),char(116),char(97),char(0),char(98),char(116),char(84),char(114),char(105),char(97),char(110),char(103),char(108),char(101),char(77),char(101),char(115),char(104),char(83),char(104),
char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(84),char(114),char(105),char(97),char(110),char(103),char(108),char(101),char(73),char(110),
-char(102),char(111),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(80),char(101),char(114),char(115),char(105),char(115),char(116),char(101),char(110),char(116),char(77),
-char(97),char(110),char(105),char(102),char(111),char(108),char(100),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),
-char(67),char(111),char(108),char(108),char(105),char(115),char(105),char(111),char(110),char(79),char(98),char(106),char(101),char(99),char(116),char(68),char(111),char(117),char(98),char(108),
-char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(80),char(101),char(114),char(115),char(105),char(115),char(116),char(101),char(110),char(116),char(77),char(97),
-char(110),char(105),char(102),char(111),char(108),char(100),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(111),
-char(108),char(108),char(105),char(115),char(105),char(111),char(110),char(79),char(98),char(106),char(101),char(99),char(116),char(70),char(108),char(111),char(97),char(116),char(68),char(97),
-char(116),char(97),char(0),char(98),char(116),char(71),char(73),char(109),char(112),char(97),char(99),char(116),char(77),char(101),char(115),char(104),char(83),char(104),char(97),char(112),
-char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(111),char(110),char(118),char(101),char(120),char(72),char(117),char(108),char(108),char(83),char(104),
-char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(111),char(110),char(116),char(97),char(99),char(116),char(83),char(111),char(108),
-char(118),char(101),char(114),char(73),char(110),char(102),char(111),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),
-char(67),char(111),char(110),char(116),char(97),char(99),char(116),char(83),char(111),char(108),char(118),char(101),char(114),char(73),char(110),char(102),char(111),char(70),char(108),char(111),
-char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(68),char(121),char(110),char(97),char(109),char(105),char(99),char(115),char(87),char(111),char(114),
-char(108),char(100),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(68),char(121),char(110),char(97),char(109),
-char(105),char(99),char(115),char(87),char(111),char(114),char(108),char(100),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),
-char(82),char(105),char(103),char(105),char(100),char(66),char(111),char(100),char(121),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),
-char(116),char(82),char(105),char(103),char(105),char(100),char(66),char(111),char(100),char(121),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),
-char(0),char(98),char(116),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(73),char(110),char(102),char(111),char(49),char(0),char(98),
-char(116),char(84),char(121),char(112),char(101),char(100),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(70),char(108),char(111),char(97),
-char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(84),char(121),char(112),char(101),char(100),char(67),char(111),char(110),char(115),char(116),char(114),char(97),
-char(105),char(110),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(82),char(105),char(103),char(105),char(100),char(66),char(111),char(100),char(121),char(68),
-char(97),char(116),char(97),char(0),char(98),char(116),char(84),char(121),char(112),char(101),char(100),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),
-char(116),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(80),char(111),char(105),char(110),char(116),char(50),
-char(80),char(111),char(105),char(110),char(116),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(70),char(108),char(111),char(97),char(116),
-char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(80),char(111),char(105),char(110),char(116),char(50),char(80),char(111),char(105),char(110),char(116),char(67),char(111),
-char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(50),char(0),
-char(98),char(116),char(80),char(111),char(105),char(110),char(116),char(50),char(80),char(111),char(105),char(110),char(116),char(67),char(111),char(110),char(115),char(116),char(114),char(97),
+char(102),char(111),char(77),char(97),char(112),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(83),char(99),char(97),char(108),char(101),char(100),char(84),char(114),
+char(105),char(97),char(110),char(103),char(108),char(101),char(77),char(101),char(115),char(104),char(83),char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),
+char(98),char(116),char(67),char(111),char(109),char(112),char(111),char(117),char(110),char(100),char(83),char(104),char(97),char(112),char(101),char(67),char(104),char(105),char(108),char(100),
+char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(111),char(109),char(112),char(111),char(117),char(110),char(100),char(83),char(104),char(97),char(112),char(101),
+char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(121),char(108),char(105),char(110),char(100),char(101),char(114),char(83),char(104),char(97),char(112),char(101),
+char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(111),char(110),char(101),char(83),char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97),
+char(0),char(98),char(116),char(67),char(97),char(112),char(115),char(117),char(108),char(101),char(83),char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),
+char(98),char(116),char(84),char(114),char(105),char(97),char(110),char(103),char(108),char(101),char(73),char(110),char(102),char(111),char(68),char(97),char(116),char(97),char(0),char(98),
+char(116),char(80),char(101),char(114),char(115),char(105),char(115),char(116),char(101),char(110),char(116),char(77),char(97),char(110),char(105),char(102),char(111),char(108),char(100),char(68),
+char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(111),char(108),char(108),char(105),char(115),char(105),char(111),
+char(110),char(79),char(98),char(106),char(101),char(99),char(116),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),
+char(80),char(101),char(114),char(115),char(105),char(115),char(116),char(101),char(110),char(116),char(77),char(97),char(110),char(105),char(102),char(111),char(108),char(100),char(70),char(108),
+char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(111),char(108),char(108),char(105),char(115),char(105),char(111),char(110),char(79),
+char(98),char(106),char(101),char(99),char(116),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(71),char(73),char(109),
+char(112),char(97),char(99),char(116),char(77),char(101),char(115),char(104),char(83),char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),
+char(67),char(111),char(110),char(118),char(101),char(120),char(72),char(117),char(108),char(108),char(83),char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),
+char(98),char(116),char(67),char(111),char(110),char(116),char(97),char(99),char(116),char(83),char(111),char(108),char(118),char(101),char(114),char(73),char(110),char(102),char(111),char(68),
+char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(111),char(110),char(116),char(97),char(99),char(116),char(83),
+char(111),char(108),char(118),char(101),char(114),char(73),char(110),char(102),char(111),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),
+char(116),char(68),char(121),char(110),char(97),char(109),char(105),char(99),char(115),char(87),char(111),char(114),char(108),char(100),char(68),char(111),char(117),char(98),char(108),char(101),
+char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(68),char(121),char(110),char(97),char(109),char(105),char(99),char(115),char(87),char(111),char(114),char(108),char(100),
+char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(82),char(105),char(103),char(105),char(100),char(66),char(111),char(100),
+char(121),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(82),char(105),char(103),char(105),char(100),char(66),char(111),
+char(100),char(121),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(111),char(110),char(115),char(116),
+char(114),char(97),char(105),char(110),char(116),char(73),char(110),char(102),char(111),char(49),char(0),char(98),char(116),char(84),char(121),char(112),char(101),char(100),char(67),char(111),
+char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),
+char(84),char(121),char(112),char(101),char(100),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(68),char(97),char(116),char(97),char(0),
+char(98),char(116),char(82),char(105),char(103),char(105),char(100),char(66),char(111),char(100),char(121),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(84),char(121),
+char(112),char(101),char(100),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(68),char(111),char(117),char(98),char(108),char(101),char(68),
+char(97),char(116),char(97),char(0),char(98),char(116),char(80),char(111),char(105),char(110),char(116),char(50),char(80),char(111),char(105),char(110),char(116),char(67),char(111),char(110),
+char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(80),
+char(111),char(105),char(110),char(116),char(50),char(80),char(111),char(105),char(110),char(116),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),
+char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(50),char(0),char(98),char(116),char(80),char(111),char(105),char(110),char(116),char(50),
+char(80),char(111),char(105),char(110),char(116),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(68),char(111),char(117),char(98),char(108),
+char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(72),char(105),char(110),char(103),char(101),char(67),char(111),char(110),char(115),char(116),char(114),char(97),
char(105),char(110),char(116),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(72),char(105),char(110),char(103),
-char(101),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),
-char(97),char(0),char(98),char(116),char(72),char(105),char(110),char(103),char(101),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(70),
-char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(72),char(105),char(110),char(103),char(101),char(67),char(111),char(110),char(115),
-char(116),char(114),char(97),char(105),char(110),char(116),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(50),char(0),char(98),char(116),
-char(67),char(111),char(110),char(101),char(84),char(119),char(105),char(115),char(116),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(68),
-char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(111),char(110),char(101),char(84),char(119),char(105),char(115),
-char(116),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(71),char(101),
+char(101),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),
+char(0),char(98),char(116),char(72),char(105),char(110),char(103),char(101),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(68),char(111),
+char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(50),char(0),char(98),char(116),char(67),char(111),char(110),char(101),char(84),char(119),char(105),char(115),
+char(116),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),
+char(97),char(0),char(98),char(116),char(67),char(111),char(110),char(101),char(84),char(119),char(105),char(115),char(116),char(67),char(111),char(110),char(115),char(116),char(114),char(97),
+char(105),char(110),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(71),char(101),char(110),char(101),char(114),char(105),char(99),char(54),char(68),char(111),
+char(102),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(71),char(101),
char(110),char(101),char(114),char(105),char(99),char(54),char(68),char(111),char(102),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(68),
-char(97),char(116),char(97),char(0),char(98),char(116),char(71),char(101),char(110),char(101),char(114),char(105),char(99),char(54),char(68),char(111),char(102),char(67),char(111),char(110),
-char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(50),char(0),char(98),
-char(116),char(71),char(101),char(110),char(101),char(114),char(105),char(99),char(54),char(68),char(111),char(102),char(83),char(112),char(114),char(105),char(110),char(103),char(67),char(111),
-char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(71),char(101),char(110),char(101),char(114),
-char(105),char(99),char(54),char(68),char(111),char(102),char(83),char(112),char(114),char(105),char(110),char(103),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),
-char(110),char(116),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(50),char(0),char(98),char(116),char(71),char(101),char(110),char(101),
-char(114),char(105),char(99),char(54),char(68),char(111),char(102),char(83),char(112),char(114),char(105),char(110),char(103),char(50),char(67),char(111),char(110),char(115),char(116),char(114),
-char(97),char(105),char(110),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(71),char(101),char(110),char(101),char(114),char(105),char(99),char(54),char(68),
-char(111),char(102),char(83),char(112),char(114),char(105),char(110),char(103),char(50),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(68),
-char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(50),char(0),char(98),char(116),char(83),char(108),char(105),char(100),char(101),char(114),char(67),
-char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(83),char(108),char(105),char(100),
-char(101),char(114),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),
-char(116),char(97),char(0),char(98),char(116),char(71),char(101),char(97),char(114),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(70),
-char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(71),char(101),char(97),char(114),char(67),char(111),char(110),char(115),char(116),
-char(114),char(97),char(105),char(110),char(116),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(83),char(111),char(102),char(116),
-char(66),char(111),char(100),char(121),char(77),char(97),char(116),char(101),char(114),char(105),char(97),char(108),char(68),char(97),char(116),char(97),char(0),char(83),char(111),char(102),
-char(116),char(66),char(111),char(100),char(121),char(78),char(111),char(100),char(101),char(68),char(97),char(116),char(97),char(0),char(83),char(111),char(102),char(116),char(66),char(111),
-char(100),char(121),char(76),char(105),char(110),char(107),char(68),char(97),char(116),char(97),char(0),char(83),char(111),char(102),char(116),char(66),char(111),char(100),char(121),char(70),
-char(97),char(99),char(101),char(68),char(97),char(116),char(97),char(0),char(83),char(111),char(102),char(116),char(66),char(111),char(100),char(121),char(84),char(101),char(116),char(114),
-char(97),char(68),char(97),char(116),char(97),char(0),char(83),char(111),char(102),char(116),char(82),char(105),char(103),char(105),char(100),char(65),char(110),char(99),char(104),char(111),
-char(114),char(68),char(97),char(116),char(97),char(0),char(83),char(111),char(102),char(116),char(66),char(111),char(100),char(121),char(67),char(111),char(110),char(102),char(105),char(103),
-char(68),char(97),char(116),char(97),char(0),char(83),char(111),char(102),char(116),char(66),char(111),char(100),char(121),char(80),char(111),char(115),char(101),char(68),char(97),char(116),
-char(97),char(0),char(83),char(111),char(102),char(116),char(66),char(111),char(100),char(121),char(67),char(108),char(117),char(115),char(116),char(101),char(114),char(68),char(97),char(116),
-char(97),char(0),char(98),char(116),char(83),char(111),char(102),char(116),char(66),char(111),char(100),char(121),char(74),char(111),char(105),char(110),char(116),char(68),char(97),char(116),
-char(97),char(0),char(98),char(116),char(83),char(111),char(102),char(116),char(66),char(111),char(100),char(121),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),
-char(97),char(0),char(98),char(116),char(77),char(117),char(108),char(116),char(105),char(66),char(111),char(100),char(121),char(76),char(105),char(110),char(107),char(68),char(111),char(117),
-char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(77),char(117),char(108),char(116),char(105),char(66),char(111),char(100),char(121),char(76),
-char(105),char(110),char(107),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(77),char(117),char(108),char(116),char(105),
-char(66),char(111),char(100),char(121),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(77),char(117),char(108),
-char(116),char(105),char(66),char(111),char(100),char(121),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(77),char(117),
-char(108),char(116),char(105),char(66),char(111),char(100),char(121),char(76),char(105),char(110),char(107),char(67),char(111),char(108),char(108),char(105),char(100),char(101),char(114),char(70),
-char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(77),char(117),char(108),char(116),char(105),char(66),char(111),char(100),char(121),
-char(76),char(105),char(110),char(107),char(67),char(111),char(108),char(108),char(105),char(100),char(101),char(114),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),
-char(116),char(97),char(0),char(0),char(84),char(76),char(69),char(78),char(1),char(0),char(1),char(0),char(2),char(0),char(2),char(0),char(4),char(0),char(4),char(0),
-char(4),char(0),char(4),char(0),char(8),char(0),char(0),char(0),char(16),char(0),char(48),char(0),char(16),char(0),char(16),char(0),char(32),char(0),char(16),char(0),
-char(32),char(0),char(48),char(0),char(96),char(0),char(64),char(0),char(-128),char(0),char(20),char(0),char(48),char(0),char(80),char(0),char(16),char(0),char(96),char(0),
-char(-112),char(0),char(16),char(0),char(56),char(0),char(56),char(0),char(20),char(0),char(72),char(0),char(4),char(0),char(4),char(0),char(8),char(0),char(4),char(0),
-char(56),char(0),char(32),char(0),char(80),char(0),char(72),char(0),char(96),char(0),char(80),char(0),char(32),char(0),char(64),char(0),char(64),char(0),char(64),char(0),
-char(16),char(0),char(-8),char(5),char(-8),char(1),char(64),char(3),char(32),char(1),char(72),char(0),char(80),char(0),char(-104),char(0),char(88),char(0),char(-72),char(0),
-char(104),char(0),char(8),char(2),char(-56),char(3),char(8),char(0),char(64),char(0),char(64),char(0),char(0),char(0),char(80),char(0),char(96),char(0),char(-112),char(0),
-char(-128),char(0),char(104),char(1),char(-24),char(0),char(-104),char(1),char(-120),char(1),char(-32),char(0),char(8),char(1),char(-40),char(1),char(104),char(1),char(-128),char(2),
-char(-112),char(2),char(-64),char(4),char(-40),char(0),char(120),char(1),char(104),char(0),char(-104),char(0),char(16),char(0),char(104),char(0),char(24),char(0),char(40),char(0),
-char(104),char(0),char(96),char(0),char(104),char(0),char(-56),char(0),char(104),char(1),char(112),char(0),char(-16),char(1),char(-128),char(3),char(-40),char(1),char(-56),char(0),
-char(112),char(0),char(48),char(1),char(8),char(2),char(0),char(0),char(83),char(84),char(82),char(67),char(88),char(0),char(0),char(0),char(10),char(0),char(3),char(0),
-char(4),char(0),char(0),char(0),char(4),char(0),char(1),char(0),char(9),char(0),char(2),char(0),char(11),char(0),char(3),char(0),char(10),char(0),char(3),char(0),
-char(10),char(0),char(4),char(0),char(10),char(0),char(5),char(0),char(12),char(0),char(2),char(0),char(9),char(0),char(6),char(0),char(9),char(0),char(7),char(0),
-char(13),char(0),char(1),char(0),char(7),char(0),char(8),char(0),char(14),char(0),char(1),char(0),char(8),char(0),char(8),char(0),char(15),char(0),char(1),char(0),
-char(7),char(0),char(8),char(0),char(16),char(0),char(1),char(0),char(8),char(0),char(8),char(0),char(17),char(0),char(1),char(0),char(13),char(0),char(9),char(0),
-char(18),char(0),char(1),char(0),char(14),char(0),char(9),char(0),char(19),char(0),char(2),char(0),char(17),char(0),char(10),char(0),char(13),char(0),char(11),char(0),
-char(20),char(0),char(2),char(0),char(18),char(0),char(10),char(0),char(14),char(0),char(11),char(0),char(21),char(0),char(4),char(0),char(4),char(0),char(12),char(0),
-char(4),char(0),char(13),char(0),char(2),char(0),char(14),char(0),char(2),char(0),char(15),char(0),char(22),char(0),char(6),char(0),char(13),char(0),char(16),char(0),
-char(13),char(0),char(17),char(0),char(4),char(0),char(18),char(0),char(4),char(0),char(19),char(0),char(4),char(0),char(20),char(0),char(0),char(0),char(21),char(0),
-char(23),char(0),char(6),char(0),char(14),char(0),char(16),char(0),char(14),char(0),char(17),char(0),char(4),char(0),char(18),char(0),char(4),char(0),char(19),char(0),
-char(4),char(0),char(20),char(0),char(0),char(0),char(21),char(0),char(24),char(0),char(3),char(0),char(2),char(0),char(14),char(0),char(2),char(0),char(15),char(0),
-char(4),char(0),char(22),char(0),char(25),char(0),char(12),char(0),char(13),char(0),char(23),char(0),char(13),char(0),char(24),char(0),char(13),char(0),char(25),char(0),
-char(4),char(0),char(26),char(0),char(4),char(0),char(27),char(0),char(4),char(0),char(28),char(0),char(4),char(0),char(29),char(0),char(22),char(0),char(30),char(0),
-char(24),char(0),char(31),char(0),char(21),char(0),char(32),char(0),char(4),char(0),char(33),char(0),char(4),char(0),char(34),char(0),char(26),char(0),char(12),char(0),
-char(14),char(0),char(23),char(0),char(14),char(0),char(24),char(0),char(14),char(0),char(25),char(0),char(4),char(0),char(26),char(0),char(4),char(0),char(27),char(0),
-char(4),char(0),char(28),char(0),char(4),char(0),char(29),char(0),char(23),char(0),char(30),char(0),char(24),char(0),char(31),char(0),char(4),char(0),char(33),char(0),
-char(4),char(0),char(34),char(0),char(21),char(0),char(32),char(0),char(27),char(0),char(3),char(0),char(0),char(0),char(35),char(0),char(4),char(0),char(36),char(0),
-char(0),char(0),char(37),char(0),char(28),char(0),char(5),char(0),char(27),char(0),char(38),char(0),char(13),char(0),char(39),char(0),char(13),char(0),char(40),char(0),
-char(7),char(0),char(41),char(0),char(0),char(0),char(21),char(0),char(29),char(0),char(5),char(0),char(27),char(0),char(38),char(0),char(13),char(0),char(39),char(0),
-char(13),char(0),char(42),char(0),char(7),char(0),char(43),char(0),char(4),char(0),char(44),char(0),char(30),char(0),char(2),char(0),char(13),char(0),char(45),char(0),
-char(7),char(0),char(46),char(0),char(31),char(0),char(4),char(0),char(29),char(0),char(47),char(0),char(30),char(0),char(48),char(0),char(4),char(0),char(49),char(0),
-char(0),char(0),char(37),char(0),char(32),char(0),char(1),char(0),char(4),char(0),char(50),char(0),char(33),char(0),char(2),char(0),char(2),char(0),char(50),char(0),
-char(0),char(0),char(51),char(0),char(34),char(0),char(2),char(0),char(2),char(0),char(52),char(0),char(0),char(0),char(51),char(0),char(35),char(0),char(2),char(0),
-char(0),char(0),char(52),char(0),char(0),char(0),char(53),char(0),char(36),char(0),char(8),char(0),char(13),char(0),char(54),char(0),char(14),char(0),char(55),char(0),
-char(32),char(0),char(56),char(0),char(34),char(0),char(57),char(0),char(35),char(0),char(58),char(0),char(33),char(0),char(59),char(0),char(4),char(0),char(60),char(0),
-char(4),char(0),char(61),char(0),char(37),char(0),char(4),char(0),char(36),char(0),char(62),char(0),char(13),char(0),char(63),char(0),char(4),char(0),char(64),char(0),
-char(0),char(0),char(37),char(0),char(38),char(0),char(7),char(0),char(27),char(0),char(38),char(0),char(37),char(0),char(65),char(0),char(25),char(0),char(66),char(0),
-char(26),char(0),char(67),char(0),char(39),char(0),char(68),char(0),char(7),char(0),char(43),char(0),char(0),char(0),char(69),char(0),char(40),char(0),char(2),char(0),
-char(38),char(0),char(70),char(0),char(13),char(0),char(39),char(0),char(41),char(0),char(4),char(0),char(19),char(0),char(71),char(0),char(27),char(0),char(72),char(0),
-char(4),char(0),char(73),char(0),char(7),char(0),char(74),char(0),char(42),char(0),char(4),char(0),char(27),char(0),char(38),char(0),char(41),char(0),char(75),char(0),
-char(4),char(0),char(76),char(0),char(7),char(0),char(43),char(0),char(43),char(0),char(3),char(0),char(29),char(0),char(47),char(0),char(4),char(0),char(77),char(0),
-char(0),char(0),char(37),char(0),char(44),char(0),char(3),char(0),char(29),char(0),char(47),char(0),char(4),char(0),char(78),char(0),char(0),char(0),char(37),char(0),
-char(45),char(0),char(3),char(0),char(29),char(0),char(47),char(0),char(4),char(0),char(77),char(0),char(0),char(0),char(37),char(0),char(46),char(0),char(4),char(0),
-char(4),char(0),char(79),char(0),char(7),char(0),char(80),char(0),char(7),char(0),char(81),char(0),char(7),char(0),char(82),char(0),char(39),char(0),char(14),char(0),
-char(4),char(0),char(83),char(0),char(4),char(0),char(84),char(0),char(46),char(0),char(85),char(0),char(4),char(0),char(86),char(0),char(7),char(0),char(87),char(0),
-char(7),char(0),char(88),char(0),char(7),char(0),char(89),char(0),char(7),char(0),char(90),char(0),char(7),char(0),char(91),char(0),char(4),char(0),char(92),char(0),
-char(4),char(0),char(93),char(0),char(4),char(0),char(94),char(0),char(4),char(0),char(95),char(0),char(0),char(0),char(37),char(0),char(47),char(0),char(38),char(0),
-char(14),char(0),char(96),char(0),char(14),char(0),char(97),char(0),char(14),char(0),char(98),char(0),char(14),char(0),char(99),char(0),char(14),char(0),char(100),char(0),
-char(14),char(0),char(101),char(0),char(14),char(0),char(102),char(0),char(8),char(0),char(103),char(0),char(8),char(0),char(104),char(0),char(8),char(0),char(105),char(0),
-char(8),char(0),char(106),char(0),char(8),char(0),char(107),char(0),char(8),char(0),char(108),char(0),char(4),char(0),char(109),char(0),char(4),char(0),char(110),char(0),
-char(4),char(0),char(111),char(0),char(4),char(0),char(112),char(0),char(4),char(0),char(113),char(0),char(8),char(0),char(114),char(0),char(8),char(0),char(115),char(0),
-char(8),char(0),char(116),char(0),char(8),char(0),char(117),char(0),char(8),char(0),char(118),char(0),char(8),char(0),char(119),char(0),char(8),char(0),char(120),char(0),
-char(8),char(0),char(121),char(0),char(8),char(0),char(122),char(0),char(4),char(0),char(123),char(0),char(4),char(0),char(124),char(0),char(4),char(0),char(125),char(0),
-char(4),char(0),char(126),char(0),char(4),char(0),char(127),char(0),char(4),char(0),char(-128),char(0),char(8),char(0),char(-127),char(0),char(8),char(0),char(-126),char(0),
-char(4),char(0),char(44),char(0),char(48),char(0),char(-125),char(0),char(48),char(0),char(-124),char(0),char(49),char(0),char(38),char(0),char(13),char(0),char(96),char(0),
-char(13),char(0),char(97),char(0),char(13),char(0),char(98),char(0),char(13),char(0),char(99),char(0),char(13),char(0),char(100),char(0),char(13),char(0),char(101),char(0),
-char(13),char(0),char(102),char(0),char(7),char(0),char(103),char(0),char(7),char(0),char(104),char(0),char(7),char(0),char(105),char(0),char(7),char(0),char(106),char(0),
-char(7),char(0),char(107),char(0),char(7),char(0),char(108),char(0),char(4),char(0),char(109),char(0),char(4),char(0),char(110),char(0),char(4),char(0),char(111),char(0),
-char(4),char(0),char(112),char(0),char(4),char(0),char(113),char(0),char(7),char(0),char(114),char(0),char(7),char(0),char(115),char(0),char(7),char(0),char(116),char(0),
-char(7),char(0),char(117),char(0),char(7),char(0),char(118),char(0),char(7),char(0),char(119),char(0),char(7),char(0),char(120),char(0),char(7),char(0),char(121),char(0),
-char(7),char(0),char(122),char(0),char(4),char(0),char(123),char(0),char(4),char(0),char(124),char(0),char(4),char(0),char(125),char(0),char(4),char(0),char(126),char(0),
-char(4),char(0),char(127),char(0),char(4),char(0),char(-128),char(0),char(7),char(0),char(-127),char(0),char(7),char(0),char(-126),char(0),char(4),char(0),char(44),char(0),
-char(50),char(0),char(-125),char(0),char(50),char(0),char(-124),char(0),char(51),char(0),char(5),char(0),char(27),char(0),char(38),char(0),char(37),char(0),char(65),char(0),
-char(13),char(0),char(39),char(0),char(7),char(0),char(43),char(0),char(4),char(0),char(-123),char(0),char(52),char(0),char(5),char(0),char(29),char(0),char(47),char(0),
-char(13),char(0),char(-122),char(0),char(14),char(0),char(-121),char(0),char(4),char(0),char(-120),char(0),char(0),char(0),char(-119),char(0),char(48),char(0),char(29),char(0),
-char(9),char(0),char(-118),char(0),char(9),char(0),char(-117),char(0),char(27),char(0),char(-116),char(0),char(0),char(0),char(35),char(0),char(20),char(0),char(-115),char(0),
-char(20),char(0),char(-114),char(0),char(14),char(0),char(-113),char(0),char(14),char(0),char(-112),char(0),char(14),char(0),char(-111),char(0),char(8),char(0),char(-126),char(0),
-char(8),char(0),char(-110),char(0),char(8),char(0),char(-109),char(0),char(8),char(0),char(-108),char(0),char(8),char(0),char(-107),char(0),char(8),char(0),char(-106),char(0),
-char(8),char(0),char(-105),char(0),char(8),char(0),char(-104),char(0),char(8),char(0),char(-103),char(0),char(8),char(0),char(-102),char(0),char(4),char(0),char(-101),char(0),
-char(4),char(0),char(-100),char(0),char(4),char(0),char(-99),char(0),char(4),char(0),char(-98),char(0),char(4),char(0),char(-97),char(0),char(4),char(0),char(-96),char(0),
-char(4),char(0),char(-95),char(0),char(4),char(0),char(-94),char(0),char(4),char(0),char(-93),char(0),char(4),char(0),char(-92),char(0),char(50),char(0),char(29),char(0),
-char(9),char(0),char(-118),char(0),char(9),char(0),char(-117),char(0),char(27),char(0),char(-116),char(0),char(0),char(0),char(35),char(0),char(19),char(0),char(-115),char(0),
-char(19),char(0),char(-114),char(0),char(13),char(0),char(-113),char(0),char(13),char(0),char(-112),char(0),char(13),char(0),char(-111),char(0),char(7),char(0),char(-126),char(0),
-char(7),char(0),char(-110),char(0),char(7),char(0),char(-109),char(0),char(7),char(0),char(-108),char(0),char(7),char(0),char(-107),char(0),char(7),char(0),char(-106),char(0),
-char(7),char(0),char(-105),char(0),char(7),char(0),char(-104),char(0),char(7),char(0),char(-103),char(0),char(7),char(0),char(-102),char(0),char(4),char(0),char(-101),char(0),
-char(4),char(0),char(-100),char(0),char(4),char(0),char(-99),char(0),char(4),char(0),char(-98),char(0),char(4),char(0),char(-97),char(0),char(4),char(0),char(-96),char(0),
-char(4),char(0),char(-95),char(0),char(4),char(0),char(-94),char(0),char(4),char(0),char(-93),char(0),char(4),char(0),char(-92),char(0),char(53),char(0),char(22),char(0),
-char(8),char(0),char(-91),char(0),char(8),char(0),char(-90),char(0),char(8),char(0),char(-109),char(0),char(8),char(0),char(-89),char(0),char(8),char(0),char(-105),char(0),
-char(8),char(0),char(-88),char(0),char(8),char(0),char(-87),char(0),char(8),char(0),char(-86),char(0),char(8),char(0),char(-85),char(0),char(8),char(0),char(-84),char(0),
-char(8),char(0),char(-83),char(0),char(8),char(0),char(-82),char(0),char(8),char(0),char(-81),char(0),char(8),char(0),char(-80),char(0),char(8),char(0),char(-79),char(0),
-char(8),char(0),char(-78),char(0),char(4),char(0),char(-77),char(0),char(4),char(0),char(-76),char(0),char(4),char(0),char(-75),char(0),char(4),char(0),char(-74),char(0),
-char(4),char(0),char(-73),char(0),char(0),char(0),char(37),char(0),char(54),char(0),char(22),char(0),char(7),char(0),char(-91),char(0),char(7),char(0),char(-90),char(0),
-char(7),char(0),char(-109),char(0),char(7),char(0),char(-89),char(0),char(7),char(0),char(-105),char(0),char(7),char(0),char(-88),char(0),char(7),char(0),char(-87),char(0),
+char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(50),char(0),char(98),char(116),char(71),char(101),char(110),char(101),char(114),char(105),char(99),
+char(54),char(68),char(111),char(102),char(83),char(112),char(114),char(105),char(110),char(103),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),
+char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(71),char(101),char(110),char(101),char(114),char(105),char(99),char(54),char(68),char(111),char(102),char(83),char(112),
+char(114),char(105),char(110),char(103),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(68),char(111),char(117),char(98),char(108),char(101),
+char(68),char(97),char(116),char(97),char(50),char(0),char(98),char(116),char(71),char(101),char(110),char(101),char(114),char(105),char(99),char(54),char(68),char(111),char(102),char(83),
+char(112),char(114),char(105),char(110),char(103),char(50),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(68),char(97),char(116),char(97),
+char(0),char(98),char(116),char(71),char(101),char(110),char(101),char(114),char(105),char(99),char(54),char(68),char(111),char(102),char(83),char(112),char(114),char(105),char(110),char(103),
+char(50),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),
+char(97),char(50),char(0),char(98),char(116),char(83),char(108),char(105),char(100),char(101),char(114),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),
+char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(83),char(108),char(105),char(100),char(101),char(114),char(67),char(111),char(110),char(115),char(116),char(114),
+char(97),char(105),char(110),char(116),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(71),char(101),char(97),
+char(114),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),
+char(0),char(98),char(116),char(71),char(101),char(97),char(114),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(68),char(111),char(117),
+char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(83),char(111),char(102),char(116),char(66),char(111),char(100),char(121),char(77),char(97),char(116),char(101),
+char(114),char(105),char(97),char(108),char(68),char(97),char(116),char(97),char(0),char(83),char(111),char(102),char(116),char(66),char(111),char(100),char(121),char(78),char(111),char(100),
+char(101),char(68),char(97),char(116),char(97),char(0),char(83),char(111),char(102),char(116),char(66),char(111),char(100),char(121),char(76),char(105),char(110),char(107),char(68),char(97),
+char(116),char(97),char(0),char(83),char(111),char(102),char(116),char(66),char(111),char(100),char(121),char(70),char(97),char(99),char(101),char(68),char(97),char(116),char(97),char(0),
+char(83),char(111),char(102),char(116),char(66),char(111),char(100),char(121),char(84),char(101),char(116),char(114),char(97),char(68),char(97),char(116),char(97),char(0),char(83),char(111),
+char(102),char(116),char(82),char(105),char(103),char(105),char(100),char(65),char(110),char(99),char(104),char(111),char(114),char(68),char(97),char(116),char(97),char(0),char(83),char(111),
+char(102),char(116),char(66),char(111),char(100),char(121),char(67),char(111),char(110),char(102),char(105),char(103),char(68),char(97),char(116),char(97),char(0),char(83),char(111),char(102),
+char(116),char(66),char(111),char(100),char(121),char(80),char(111),char(115),char(101),char(68),char(97),char(116),char(97),char(0),char(83),char(111),char(102),char(116),char(66),char(111),
+char(100),char(121),char(67),char(108),char(117),char(115),char(116),char(101),char(114),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(83),char(111),char(102),char(116),
+char(66),char(111),char(100),char(121),char(74),char(111),char(105),char(110),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(83),char(111),char(102),char(116),
+char(66),char(111),char(100),char(121),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(77),char(117),char(108),char(116),
+char(105),char(66),char(111),char(100),char(121),char(76),char(105),char(110),char(107),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),
+char(98),char(116),char(77),char(117),char(108),char(116),char(105),char(66),char(111),char(100),char(121),char(76),char(105),char(110),char(107),char(70),char(108),char(111),char(97),char(116),
+char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(77),char(117),char(108),char(116),char(105),char(66),char(111),char(100),char(121),char(68),char(111),char(117),char(98),
+char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(77),char(117),char(108),char(116),char(105),char(66),char(111),char(100),char(121),char(70),char(108),
+char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(77),char(117),char(108),char(116),char(105),char(66),char(111),char(100),char(121),char(76),
+char(105),char(110),char(107),char(67),char(111),char(108),char(108),char(105),char(100),char(101),char(114),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),
+char(0),char(98),char(116),char(77),char(117),char(108),char(116),char(105),char(66),char(111),char(100),char(121),char(76),char(105),char(110),char(107),char(67),char(111),char(108),char(108),
+char(105),char(100),char(101),char(114),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(0),char(84),char(76),char(69),char(78),
+char(1),char(0),char(1),char(0),char(2),char(0),char(2),char(0),char(4),char(0),char(4),char(0),char(4),char(0),char(4),char(0),char(8),char(0),char(0),char(0),
+char(16),char(0),char(48),char(0),char(16),char(0),char(16),char(0),char(32),char(0),char(16),char(0),char(32),char(0),char(48),char(0),char(96),char(0),char(64),char(0),
+char(-128),char(0),char(20),char(0),char(48),char(0),char(80),char(0),char(16),char(0),char(96),char(0),char(-112),char(0),char(16),char(0),char(56),char(0),char(56),char(0),
+char(20),char(0),char(72),char(0),char(4),char(0),char(4),char(0),char(8),char(0),char(4),char(0),char(56),char(0),char(32),char(0),char(80),char(0),char(72),char(0),
+char(96),char(0),char(80),char(0),char(32),char(0),char(64),char(0),char(64),char(0),char(64),char(0),char(16),char(0),char(24),char(6),char(-8),char(1),char(80),char(3),
+char(32),char(1),char(72),char(0),char(80),char(0),char(-96),char(0),char(88),char(0),char(-64),char(0),char(104),char(0),char(8),char(2),char(-56),char(3),char(8),char(0),
+char(64),char(0),char(64),char(0),char(0),char(0),char(80),char(0),char(96),char(0),char(-112),char(0),char(-128),char(0),char(104),char(1),char(-24),char(0),char(-104),char(1),
+char(-120),char(1),char(-32),char(0),char(8),char(1),char(-40),char(1),char(104),char(1),char(-128),char(2),char(-112),char(2),char(-64),char(4),char(-40),char(0),char(120),char(1),
+char(104),char(0),char(-104),char(0),char(16),char(0),char(104),char(0),char(24),char(0),char(40),char(0),char(104),char(0),char(96),char(0),char(104),char(0),char(-56),char(0),
+char(104),char(1),char(112),char(0),char(-16),char(1),char(-128),char(3),char(-40),char(1),char(-56),char(0),char(112),char(0),char(48),char(1),char(8),char(2),char(0),char(0),
+char(83),char(84),char(82),char(67),char(88),char(0),char(0),char(0),char(10),char(0),char(3),char(0),char(4),char(0),char(0),char(0),char(4),char(0),char(1),char(0),
+char(9),char(0),char(2),char(0),char(11),char(0),char(3),char(0),char(10),char(0),char(3),char(0),char(10),char(0),char(4),char(0),char(10),char(0),char(5),char(0),
+char(12),char(0),char(2),char(0),char(9),char(0),char(6),char(0),char(9),char(0),char(7),char(0),char(13),char(0),char(1),char(0),char(7),char(0),char(8),char(0),
+char(14),char(0),char(1),char(0),char(8),char(0),char(8),char(0),char(15),char(0),char(1),char(0),char(7),char(0),char(8),char(0),char(16),char(0),char(1),char(0),
+char(8),char(0),char(8),char(0),char(17),char(0),char(1),char(0),char(13),char(0),char(9),char(0),char(18),char(0),char(1),char(0),char(14),char(0),char(9),char(0),
+char(19),char(0),char(2),char(0),char(17),char(0),char(10),char(0),char(13),char(0),char(11),char(0),char(20),char(0),char(2),char(0),char(18),char(0),char(10),char(0),
+char(14),char(0),char(11),char(0),char(21),char(0),char(4),char(0),char(4),char(0),char(12),char(0),char(4),char(0),char(13),char(0),char(2),char(0),char(14),char(0),
+char(2),char(0),char(15),char(0),char(22),char(0),char(6),char(0),char(13),char(0),char(16),char(0),char(13),char(0),char(17),char(0),char(4),char(0),char(18),char(0),
+char(4),char(0),char(19),char(0),char(4),char(0),char(20),char(0),char(0),char(0),char(21),char(0),char(23),char(0),char(6),char(0),char(14),char(0),char(16),char(0),
+char(14),char(0),char(17),char(0),char(4),char(0),char(18),char(0),char(4),char(0),char(19),char(0),char(4),char(0),char(20),char(0),char(0),char(0),char(21),char(0),
+char(24),char(0),char(3),char(0),char(2),char(0),char(14),char(0),char(2),char(0),char(15),char(0),char(4),char(0),char(22),char(0),char(25),char(0),char(12),char(0),
+char(13),char(0),char(23),char(0),char(13),char(0),char(24),char(0),char(13),char(0),char(25),char(0),char(4),char(0),char(26),char(0),char(4),char(0),char(27),char(0),
+char(4),char(0),char(28),char(0),char(4),char(0),char(29),char(0),char(22),char(0),char(30),char(0),char(24),char(0),char(31),char(0),char(21),char(0),char(32),char(0),
+char(4),char(0),char(33),char(0),char(4),char(0),char(34),char(0),char(26),char(0),char(12),char(0),char(14),char(0),char(23),char(0),char(14),char(0),char(24),char(0),
+char(14),char(0),char(25),char(0),char(4),char(0),char(26),char(0),char(4),char(0),char(27),char(0),char(4),char(0),char(28),char(0),char(4),char(0),char(29),char(0),
+char(23),char(0),char(30),char(0),char(24),char(0),char(31),char(0),char(4),char(0),char(33),char(0),char(4),char(0),char(34),char(0),char(21),char(0),char(32),char(0),
+char(27),char(0),char(3),char(0),char(0),char(0),char(35),char(0),char(4),char(0),char(36),char(0),char(0),char(0),char(37),char(0),char(28),char(0),char(5),char(0),
+char(27),char(0),char(38),char(0),char(13),char(0),char(39),char(0),char(13),char(0),char(40),char(0),char(7),char(0),char(41),char(0),char(0),char(0),char(21),char(0),
+char(29),char(0),char(5),char(0),char(27),char(0),char(38),char(0),char(13),char(0),char(39),char(0),char(13),char(0),char(42),char(0),char(7),char(0),char(43),char(0),
+char(4),char(0),char(44),char(0),char(30),char(0),char(2),char(0),char(13),char(0),char(45),char(0),char(7),char(0),char(46),char(0),char(31),char(0),char(4),char(0),
+char(29),char(0),char(47),char(0),char(30),char(0),char(48),char(0),char(4),char(0),char(49),char(0),char(0),char(0),char(37),char(0),char(32),char(0),char(1),char(0),
+char(4),char(0),char(50),char(0),char(33),char(0),char(2),char(0),char(2),char(0),char(50),char(0),char(0),char(0),char(51),char(0),char(34),char(0),char(2),char(0),
+char(2),char(0),char(52),char(0),char(0),char(0),char(51),char(0),char(35),char(0),char(2),char(0),char(0),char(0),char(52),char(0),char(0),char(0),char(53),char(0),
+char(36),char(0),char(8),char(0),char(13),char(0),char(54),char(0),char(14),char(0),char(55),char(0),char(32),char(0),char(56),char(0),char(34),char(0),char(57),char(0),
+char(35),char(0),char(58),char(0),char(33),char(0),char(59),char(0),char(4),char(0),char(60),char(0),char(4),char(0),char(61),char(0),char(37),char(0),char(4),char(0),
+char(36),char(0),char(62),char(0),char(13),char(0),char(63),char(0),char(4),char(0),char(64),char(0),char(0),char(0),char(37),char(0),char(38),char(0),char(7),char(0),
+char(27),char(0),char(38),char(0),char(37),char(0),char(65),char(0),char(25),char(0),char(66),char(0),char(26),char(0),char(67),char(0),char(39),char(0),char(68),char(0),
+char(7),char(0),char(43),char(0),char(0),char(0),char(69),char(0),char(40),char(0),char(2),char(0),char(38),char(0),char(70),char(0),char(13),char(0),char(39),char(0),
+char(41),char(0),char(4),char(0),char(19),char(0),char(71),char(0),char(27),char(0),char(72),char(0),char(4),char(0),char(73),char(0),char(7),char(0),char(74),char(0),
+char(42),char(0),char(4),char(0),char(27),char(0),char(38),char(0),char(41),char(0),char(75),char(0),char(4),char(0),char(76),char(0),char(7),char(0),char(43),char(0),
+char(43),char(0),char(3),char(0),char(29),char(0),char(47),char(0),char(4),char(0),char(77),char(0),char(0),char(0),char(37),char(0),char(44),char(0),char(3),char(0),
+char(29),char(0),char(47),char(0),char(4),char(0),char(78),char(0),char(0),char(0),char(37),char(0),char(45),char(0),char(3),char(0),char(29),char(0),char(47),char(0),
+char(4),char(0),char(77),char(0),char(0),char(0),char(37),char(0),char(46),char(0),char(4),char(0),char(4),char(0),char(79),char(0),char(7),char(0),char(80),char(0),
+char(7),char(0),char(81),char(0),char(7),char(0),char(82),char(0),char(39),char(0),char(14),char(0),char(4),char(0),char(83),char(0),char(4),char(0),char(84),char(0),
+char(46),char(0),char(85),char(0),char(4),char(0),char(86),char(0),char(7),char(0),char(87),char(0),char(7),char(0),char(88),char(0),char(7),char(0),char(89),char(0),
+char(7),char(0),char(90),char(0),char(7),char(0),char(91),char(0),char(4),char(0),char(92),char(0),char(4),char(0),char(93),char(0),char(4),char(0),char(94),char(0),
+char(4),char(0),char(95),char(0),char(0),char(0),char(37),char(0),char(47),char(0),char(39),char(0),char(14),char(0),char(96),char(0),char(14),char(0),char(97),char(0),
+char(14),char(0),char(98),char(0),char(14),char(0),char(99),char(0),char(14),char(0),char(100),char(0),char(14),char(0),char(101),char(0),char(14),char(0),char(102),char(0),
+char(8),char(0),char(103),char(0),char(8),char(0),char(104),char(0),char(8),char(0),char(105),char(0),char(8),char(0),char(106),char(0),char(8),char(0),char(107),char(0),
+char(8),char(0),char(108),char(0),char(8),char(0),char(109),char(0),char(4),char(0),char(110),char(0),char(4),char(0),char(111),char(0),char(4),char(0),char(112),char(0),
+char(4),char(0),char(113),char(0),char(4),char(0),char(114),char(0),char(8),char(0),char(115),char(0),char(8),char(0),char(116),char(0),char(8),char(0),char(117),char(0),
+char(8),char(0),char(118),char(0),char(8),char(0),char(119),char(0),char(8),char(0),char(120),char(0),char(8),char(0),char(121),char(0),char(8),char(0),char(122),char(0),
+char(8),char(0),char(123),char(0),char(4),char(0),char(124),char(0),char(4),char(0),char(125),char(0),char(4),char(0),char(126),char(0),char(4),char(0),char(127),char(0),
+char(4),char(0),char(-128),char(0),char(4),char(0),char(-127),char(0),char(8),char(0),char(-126),char(0),char(8),char(0),char(-125),char(0),char(4),char(0),char(44),char(0),
+char(48),char(0),char(-124),char(0),char(48),char(0),char(-123),char(0),char(49),char(0),char(39),char(0),char(13),char(0),char(96),char(0),char(13),char(0),char(97),char(0),
+char(13),char(0),char(98),char(0),char(13),char(0),char(99),char(0),char(13),char(0),char(100),char(0),char(13),char(0),char(101),char(0),char(13),char(0),char(102),char(0),
+char(7),char(0),char(103),char(0),char(7),char(0),char(104),char(0),char(7),char(0),char(105),char(0),char(7),char(0),char(106),char(0),char(7),char(0),char(107),char(0),
+char(7),char(0),char(108),char(0),char(7),char(0),char(109),char(0),char(4),char(0),char(110),char(0),char(4),char(0),char(111),char(0),char(4),char(0),char(112),char(0),
+char(4),char(0),char(113),char(0),char(4),char(0),char(114),char(0),char(7),char(0),char(115),char(0),char(7),char(0),char(116),char(0),char(7),char(0),char(117),char(0),
+char(7),char(0),char(118),char(0),char(7),char(0),char(119),char(0),char(7),char(0),char(120),char(0),char(7),char(0),char(121),char(0),char(7),char(0),char(122),char(0),
+char(7),char(0),char(123),char(0),char(4),char(0),char(124),char(0),char(4),char(0),char(125),char(0),char(4),char(0),char(126),char(0),char(4),char(0),char(127),char(0),
+char(4),char(0),char(-128),char(0),char(4),char(0),char(-127),char(0),char(7),char(0),char(-126),char(0),char(7),char(0),char(-125),char(0),char(4),char(0),char(44),char(0),
+char(50),char(0),char(-124),char(0),char(50),char(0),char(-123),char(0),char(51),char(0),char(5),char(0),char(27),char(0),char(38),char(0),char(37),char(0),char(65),char(0),
+char(13),char(0),char(39),char(0),char(7),char(0),char(43),char(0),char(4),char(0),char(-122),char(0),char(52),char(0),char(5),char(0),char(29),char(0),char(47),char(0),
+char(13),char(0),char(-121),char(0),char(14),char(0),char(-120),char(0),char(4),char(0),char(-119),char(0),char(0),char(0),char(-118),char(0),char(48),char(0),char(29),char(0),
+char(9),char(0),char(-117),char(0),char(9),char(0),char(-116),char(0),char(27),char(0),char(-115),char(0),char(0),char(0),char(35),char(0),char(20),char(0),char(-114),char(0),
+char(20),char(0),char(-113),char(0),char(14),char(0),char(-112),char(0),char(14),char(0),char(-111),char(0),char(14),char(0),char(-110),char(0),char(8),char(0),char(-125),char(0),
+char(8),char(0),char(-109),char(0),char(8),char(0),char(-108),char(0),char(8),char(0),char(-107),char(0),char(8),char(0),char(-106),char(0),char(8),char(0),char(-105),char(0),
+char(8),char(0),char(-104),char(0),char(8),char(0),char(-103),char(0),char(8),char(0),char(-102),char(0),char(8),char(0),char(-101),char(0),char(4),char(0),char(-100),char(0),
+char(4),char(0),char(-99),char(0),char(4),char(0),char(-98),char(0),char(4),char(0),char(-97),char(0),char(4),char(0),char(-96),char(0),char(4),char(0),char(-95),char(0),
+char(4),char(0),char(-94),char(0),char(4),char(0),char(-93),char(0),char(4),char(0),char(-92),char(0),char(4),char(0),char(-91),char(0),char(50),char(0),char(29),char(0),
+char(9),char(0),char(-117),char(0),char(9),char(0),char(-116),char(0),char(27),char(0),char(-115),char(0),char(0),char(0),char(35),char(0),char(19),char(0),char(-114),char(0),
+char(19),char(0),char(-113),char(0),char(13),char(0),char(-112),char(0),char(13),char(0),char(-111),char(0),char(13),char(0),char(-110),char(0),char(7),char(0),char(-125),char(0),
+char(7),char(0),char(-109),char(0),char(7),char(0),char(-108),char(0),char(7),char(0),char(-107),char(0),char(7),char(0),char(-106),char(0),char(7),char(0),char(-105),char(0),
+char(7),char(0),char(-104),char(0),char(7),char(0),char(-103),char(0),char(7),char(0),char(-102),char(0),char(7),char(0),char(-101),char(0),char(4),char(0),char(-100),char(0),
+char(4),char(0),char(-99),char(0),char(4),char(0),char(-98),char(0),char(4),char(0),char(-97),char(0),char(4),char(0),char(-96),char(0),char(4),char(0),char(-95),char(0),
+char(4),char(0),char(-94),char(0),char(4),char(0),char(-93),char(0),char(4),char(0),char(-92),char(0),char(4),char(0),char(-91),char(0),char(53),char(0),char(23),char(0),
+char(8),char(0),char(-90),char(0),char(8),char(0),char(-89),char(0),char(8),char(0),char(-108),char(0),char(8),char(0),char(-88),char(0),char(8),char(0),char(-104),char(0),
+char(8),char(0),char(-87),char(0),char(8),char(0),char(-86),char(0),char(8),char(0),char(-85),char(0),char(8),char(0),char(-84),char(0),char(8),char(0),char(-83),char(0),
+char(8),char(0),char(-82),char(0),char(8),char(0),char(-81),char(0),char(8),char(0),char(-80),char(0),char(8),char(0),char(-79),char(0),char(8),char(0),char(-78),char(0),
+char(8),char(0),char(-77),char(0),char(8),char(0),char(-76),char(0),char(4),char(0),char(-75),char(0),char(4),char(0),char(-74),char(0),char(4),char(0),char(-73),char(0),
+char(4),char(0),char(-72),char(0),char(4),char(0),char(-71),char(0),char(0),char(0),char(37),char(0),char(54),char(0),char(22),char(0),char(7),char(0),char(-90),char(0),
+char(7),char(0),char(-89),char(0),char(7),char(0),char(-108),char(0),char(7),char(0),char(-88),char(0),char(7),char(0),char(-104),char(0),char(7),char(0),char(-87),char(0),
char(7),char(0),char(-86),char(0),char(7),char(0),char(-85),char(0),char(7),char(0),char(-84),char(0),char(7),char(0),char(-83),char(0),char(7),char(0),char(-82),char(0),
-char(7),char(0),char(-81),char(0),char(7),char(0),char(-80),char(0),char(7),char(0),char(-79),char(0),char(7),char(0),char(-78),char(0),char(4),char(0),char(-77),char(0),
-char(4),char(0),char(-76),char(0),char(4),char(0),char(-75),char(0),char(4),char(0),char(-74),char(0),char(4),char(0),char(-73),char(0),char(0),char(0),char(37),char(0),
-char(55),char(0),char(2),char(0),char(53),char(0),char(-72),char(0),char(14),char(0),char(-71),char(0),char(56),char(0),char(2),char(0),char(54),char(0),char(-72),char(0),
-char(13),char(0),char(-71),char(0),char(57),char(0),char(21),char(0),char(50),char(0),char(-70),char(0),char(17),char(0),char(-69),char(0),char(13),char(0),char(-68),char(0),
-char(13),char(0),char(-67),char(0),char(13),char(0),char(-66),char(0),char(13),char(0),char(-65),char(0),char(13),char(0),char(-71),char(0),char(13),char(0),char(-64),char(0),
-char(13),char(0),char(-63),char(0),char(13),char(0),char(-62),char(0),char(13),char(0),char(-61),char(0),char(7),char(0),char(-60),char(0),char(7),char(0),char(-59),char(0),
-char(7),char(0),char(-58),char(0),char(7),char(0),char(-57),char(0),char(7),char(0),char(-56),char(0),char(7),char(0),char(-55),char(0),char(7),char(0),char(-54),char(0),
-char(7),char(0),char(-53),char(0),char(7),char(0),char(-52),char(0),char(4),char(0),char(-51),char(0),char(58),char(0),char(22),char(0),char(48),char(0),char(-70),char(0),
-char(18),char(0),char(-69),char(0),char(14),char(0),char(-68),char(0),char(14),char(0),char(-67),char(0),char(14),char(0),char(-66),char(0),char(14),char(0),char(-65),char(0),
-char(14),char(0),char(-71),char(0),char(14),char(0),char(-64),char(0),char(14),char(0),char(-63),char(0),char(14),char(0),char(-62),char(0),char(14),char(0),char(-61),char(0),
-char(8),char(0),char(-60),char(0),char(8),char(0),char(-59),char(0),char(8),char(0),char(-58),char(0),char(8),char(0),char(-57),char(0),char(8),char(0),char(-56),char(0),
-char(8),char(0),char(-55),char(0),char(8),char(0),char(-54),char(0),char(8),char(0),char(-53),char(0),char(8),char(0),char(-52),char(0),char(4),char(0),char(-51),char(0),
-char(0),char(0),char(37),char(0),char(59),char(0),char(2),char(0),char(4),char(0),char(-50),char(0),char(4),char(0),char(-49),char(0),char(60),char(0),char(13),char(0),
-char(57),char(0),char(-48),char(0),char(57),char(0),char(-47),char(0),char(0),char(0),char(35),char(0),char(4),char(0),char(-128),char(0),char(4),char(0),char(-46),char(0),
-char(4),char(0),char(-45),char(0),char(4),char(0),char(-44),char(0),char(7),char(0),char(-43),char(0),char(7),char(0),char(-42),char(0),char(4),char(0),char(-41),char(0),
-char(4),char(0),char(-40),char(0),char(7),char(0),char(-39),char(0),char(4),char(0),char(-38),char(0),char(61),char(0),char(13),char(0),char(62),char(0),char(-48),char(0),
-char(62),char(0),char(-47),char(0),char(0),char(0),char(35),char(0),char(4),char(0),char(-128),char(0),char(4),char(0),char(-46),char(0),char(4),char(0),char(-45),char(0),
-char(4),char(0),char(-44),char(0),char(7),char(0),char(-43),char(0),char(7),char(0),char(-42),char(0),char(4),char(0),char(-41),char(0),char(4),char(0),char(-40),char(0),
-char(7),char(0),char(-39),char(0),char(4),char(0),char(-38),char(0),char(63),char(0),char(14),char(0),char(58),char(0),char(-48),char(0),char(58),char(0),char(-47),char(0),
-char(0),char(0),char(35),char(0),char(4),char(0),char(-128),char(0),char(4),char(0),char(-46),char(0),char(4),char(0),char(-45),char(0),char(4),char(0),char(-44),char(0),
-char(8),char(0),char(-43),char(0),char(8),char(0),char(-42),char(0),char(4),char(0),char(-41),char(0),char(4),char(0),char(-40),char(0),char(8),char(0),char(-39),char(0),
-char(4),char(0),char(-38),char(0),char(0),char(0),char(-37),char(0),char(64),char(0),char(3),char(0),char(61),char(0),char(-36),char(0),char(13),char(0),char(-35),char(0),
-char(13),char(0),char(-34),char(0),char(65),char(0),char(3),char(0),char(63),char(0),char(-36),char(0),char(14),char(0),char(-35),char(0),char(14),char(0),char(-34),char(0),
-char(66),char(0),char(3),char(0),char(61),char(0),char(-36),char(0),char(14),char(0),char(-35),char(0),char(14),char(0),char(-34),char(0),char(67),char(0),char(13),char(0),
-char(61),char(0),char(-36),char(0),char(20),char(0),char(-33),char(0),char(20),char(0),char(-32),char(0),char(4),char(0),char(-31),char(0),char(4),char(0),char(-30),char(0),
-char(4),char(0),char(-29),char(0),char(7),char(0),char(-28),char(0),char(7),char(0),char(-27),char(0),char(7),char(0),char(-26),char(0),char(7),char(0),char(-25),char(0),
-char(7),char(0),char(-24),char(0),char(7),char(0),char(-23),char(0),char(7),char(0),char(-22),char(0),char(68),char(0),char(13),char(0),char(61),char(0),char(-36),char(0),
-char(19),char(0),char(-33),char(0),char(19),char(0),char(-32),char(0),char(4),char(0),char(-31),char(0),char(4),char(0),char(-30),char(0),char(4),char(0),char(-29),char(0),
-char(7),char(0),char(-28),char(0),char(7),char(0),char(-27),char(0),char(7),char(0),char(-26),char(0),char(7),char(0),char(-25),char(0),char(7),char(0),char(-24),char(0),
-char(7),char(0),char(-23),char(0),char(7),char(0),char(-22),char(0),char(69),char(0),char(14),char(0),char(63),char(0),char(-36),char(0),char(20),char(0),char(-33),char(0),
-char(20),char(0),char(-32),char(0),char(4),char(0),char(-31),char(0),char(4),char(0),char(-30),char(0),char(4),char(0),char(-29),char(0),char(8),char(0),char(-28),char(0),
-char(8),char(0),char(-27),char(0),char(8),char(0),char(-26),char(0),char(8),char(0),char(-25),char(0),char(8),char(0),char(-24),char(0),char(8),char(0),char(-23),char(0),
-char(8),char(0),char(-22),char(0),char(0),char(0),char(-21),char(0),char(70),char(0),char(10),char(0),char(63),char(0),char(-36),char(0),char(20),char(0),char(-33),char(0),
-char(20),char(0),char(-32),char(0),char(8),char(0),char(-20),char(0),char(8),char(0),char(-19),char(0),char(8),char(0),char(-18),char(0),char(8),char(0),char(-24),char(0),
-char(8),char(0),char(-23),char(0),char(8),char(0),char(-22),char(0),char(8),char(0),char(-90),char(0),char(71),char(0),char(11),char(0),char(61),char(0),char(-36),char(0),
-char(19),char(0),char(-33),char(0),char(19),char(0),char(-32),char(0),char(7),char(0),char(-20),char(0),char(7),char(0),char(-19),char(0),char(7),char(0),char(-18),char(0),
-char(7),char(0),char(-24),char(0),char(7),char(0),char(-23),char(0),char(7),char(0),char(-22),char(0),char(7),char(0),char(-90),char(0),char(0),char(0),char(21),char(0),
-char(72),char(0),char(9),char(0),char(61),char(0),char(-36),char(0),char(19),char(0),char(-33),char(0),char(19),char(0),char(-32),char(0),char(13),char(0),char(-17),char(0),
-char(13),char(0),char(-16),char(0),char(13),char(0),char(-15),char(0),char(13),char(0),char(-14),char(0),char(4),char(0),char(-13),char(0),char(4),char(0),char(-12),char(0),
-char(73),char(0),char(9),char(0),char(63),char(0),char(-36),char(0),char(20),char(0),char(-33),char(0),char(20),char(0),char(-32),char(0),char(14),char(0),char(-17),char(0),
-char(14),char(0),char(-16),char(0),char(14),char(0),char(-15),char(0),char(14),char(0),char(-14),char(0),char(4),char(0),char(-13),char(0),char(4),char(0),char(-12),char(0),
-char(74),char(0),char(5),char(0),char(72),char(0),char(-11),char(0),char(4),char(0),char(-10),char(0),char(7),char(0),char(-9),char(0),char(7),char(0),char(-8),char(0),
-char(7),char(0),char(-7),char(0),char(75),char(0),char(5),char(0),char(73),char(0),char(-11),char(0),char(4),char(0),char(-10),char(0),char(8),char(0),char(-9),char(0),
-char(8),char(0),char(-8),char(0),char(8),char(0),char(-7),char(0),char(76),char(0),char(41),char(0),char(61),char(0),char(-36),char(0),char(19),char(0),char(-33),char(0),
-char(19),char(0),char(-32),char(0),char(13),char(0),char(-17),char(0),char(13),char(0),char(-16),char(0),char(13),char(0),char(-6),char(0),char(13),char(0),char(-5),char(0),
-char(13),char(0),char(-4),char(0),char(13),char(0),char(-3),char(0),char(13),char(0),char(-2),char(0),char(13),char(0),char(-1),char(0),char(13),char(0),char(0),char(1),
-char(13),char(0),char(1),char(1),char(13),char(0),char(2),char(1),char(13),char(0),char(3),char(1),char(13),char(0),char(4),char(1),char(0),char(0),char(5),char(1),
-char(0),char(0),char(6),char(1),char(0),char(0),char(7),char(1),char(0),char(0),char(8),char(1),char(0),char(0),char(9),char(1),char(0),char(0),char(-21),char(0),
-char(13),char(0),char(-15),char(0),char(13),char(0),char(-14),char(0),char(13),char(0),char(10),char(1),char(13),char(0),char(11),char(1),char(13),char(0),char(12),char(1),
-char(13),char(0),char(13),char(1),char(13),char(0),char(14),char(1),char(13),char(0),char(15),char(1),char(13),char(0),char(16),char(1),char(13),char(0),char(17),char(1),
-char(13),char(0),char(18),char(1),char(13),char(0),char(19),char(1),char(13),char(0),char(20),char(1),char(0),char(0),char(21),char(1),char(0),char(0),char(22),char(1),
-char(0),char(0),char(23),char(1),char(0),char(0),char(24),char(1),char(0),char(0),char(25),char(1),char(4),char(0),char(26),char(1),char(77),char(0),char(41),char(0),
-char(63),char(0),char(-36),char(0),char(20),char(0),char(-33),char(0),char(20),char(0),char(-32),char(0),char(14),char(0),char(-17),char(0),char(14),char(0),char(-16),char(0),
-char(14),char(0),char(-6),char(0),char(14),char(0),char(-5),char(0),char(14),char(0),char(-4),char(0),char(14),char(0),char(-3),char(0),char(14),char(0),char(-2),char(0),
-char(14),char(0),char(-1),char(0),char(14),char(0),char(0),char(1),char(14),char(0),char(1),char(1),char(14),char(0),char(2),char(1),char(14),char(0),char(3),char(1),
-char(14),char(0),char(4),char(1),char(0),char(0),char(5),char(1),char(0),char(0),char(6),char(1),char(0),char(0),char(7),char(1),char(0),char(0),char(8),char(1),
-char(0),char(0),char(9),char(1),char(0),char(0),char(-21),char(0),char(14),char(0),char(-15),char(0),char(14),char(0),char(-14),char(0),char(14),char(0),char(10),char(1),
-char(14),char(0),char(11),char(1),char(14),char(0),char(12),char(1),char(14),char(0),char(13),char(1),char(14),char(0),char(14),char(1),char(14),char(0),char(15),char(1),
-char(14),char(0),char(16),char(1),char(14),char(0),char(17),char(1),char(14),char(0),char(18),char(1),char(14),char(0),char(19),char(1),char(14),char(0),char(20),char(1),
-char(0),char(0),char(21),char(1),char(0),char(0),char(22),char(1),char(0),char(0),char(23),char(1),char(0),char(0),char(24),char(1),char(0),char(0),char(25),char(1),
-char(4),char(0),char(26),char(1),char(78),char(0),char(9),char(0),char(61),char(0),char(-36),char(0),char(19),char(0),char(-33),char(0),char(19),char(0),char(-32),char(0),
-char(7),char(0),char(-17),char(0),char(7),char(0),char(-16),char(0),char(7),char(0),char(-15),char(0),char(7),char(0),char(-14),char(0),char(4),char(0),char(-13),char(0),
-char(4),char(0),char(-12),char(0),char(79),char(0),char(9),char(0),char(63),char(0),char(-36),char(0),char(20),char(0),char(-33),char(0),char(20),char(0),char(-32),char(0),
-char(8),char(0),char(-17),char(0),char(8),char(0),char(-16),char(0),char(8),char(0),char(-15),char(0),char(8),char(0),char(-14),char(0),char(4),char(0),char(-13),char(0),
-char(4),char(0),char(-12),char(0),char(80),char(0),char(5),char(0),char(60),char(0),char(-36),char(0),char(13),char(0),char(27),char(1),char(13),char(0),char(28),char(1),
-char(7),char(0),char(29),char(1),char(0),char(0),char(37),char(0),char(81),char(0),char(4),char(0),char(63),char(0),char(-36),char(0),char(14),char(0),char(27),char(1),
-char(14),char(0),char(28),char(1),char(8),char(0),char(29),char(1),char(82),char(0),char(4),char(0),char(7),char(0),char(30),char(1),char(7),char(0),char(31),char(1),
-char(7),char(0),char(32),char(1),char(4),char(0),char(79),char(0),char(83),char(0),char(10),char(0),char(82),char(0),char(33),char(1),char(13),char(0),char(34),char(1),
-char(13),char(0),char(35),char(1),char(13),char(0),char(36),char(1),char(13),char(0),char(37),char(1),char(13),char(0),char(38),char(1),char(7),char(0),char(-60),char(0),
-char(7),char(0),char(39),char(1),char(4),char(0),char(40),char(1),char(4),char(0),char(53),char(0),char(84),char(0),char(4),char(0),char(82),char(0),char(33),char(1),
-char(4),char(0),char(41),char(1),char(7),char(0),char(42),char(1),char(4),char(0),char(43),char(1),char(85),char(0),char(4),char(0),char(13),char(0),char(38),char(1),
-char(82),char(0),char(33),char(1),char(4),char(0),char(44),char(1),char(7),char(0),char(45),char(1),char(86),char(0),char(7),char(0),char(13),char(0),char(46),char(1),
-char(82),char(0),char(33),char(1),char(4),char(0),char(47),char(1),char(7),char(0),char(48),char(1),char(7),char(0),char(49),char(1),char(7),char(0),char(50),char(1),
-char(4),char(0),char(53),char(0),char(87),char(0),char(6),char(0),char(17),char(0),char(51),char(1),char(13),char(0),char(49),char(1),char(13),char(0),char(52),char(1),
-char(62),char(0),char(53),char(1),char(4),char(0),char(54),char(1),char(7),char(0),char(50),char(1),char(88),char(0),char(26),char(0),char(4),char(0),char(55),char(1),
-char(7),char(0),char(56),char(1),char(7),char(0),char(-90),char(0),char(7),char(0),char(57),char(1),char(7),char(0),char(58),char(1),char(7),char(0),char(59),char(1),
-char(7),char(0),char(60),char(1),char(7),char(0),char(61),char(1),char(7),char(0),char(62),char(1),char(7),char(0),char(63),char(1),char(7),char(0),char(64),char(1),
-char(7),char(0),char(65),char(1),char(7),char(0),char(66),char(1),char(7),char(0),char(67),char(1),char(7),char(0),char(68),char(1),char(7),char(0),char(69),char(1),
-char(7),char(0),char(70),char(1),char(7),char(0),char(71),char(1),char(7),char(0),char(72),char(1),char(7),char(0),char(73),char(1),char(7),char(0),char(74),char(1),
-char(4),char(0),char(75),char(1),char(4),char(0),char(76),char(1),char(4),char(0),char(77),char(1),char(4),char(0),char(78),char(1),char(4),char(0),char(-100),char(0),
-char(89),char(0),char(12),char(0),char(17),char(0),char(79),char(1),char(17),char(0),char(80),char(1),char(17),char(0),char(81),char(1),char(13),char(0),char(82),char(1),
-char(13),char(0),char(83),char(1),char(7),char(0),char(84),char(1),char(4),char(0),char(85),char(1),char(4),char(0),char(86),char(1),char(4),char(0),char(87),char(1),
-char(4),char(0),char(88),char(1),char(7),char(0),char(48),char(1),char(4),char(0),char(53),char(0),char(90),char(0),char(27),char(0),char(19),char(0),char(89),char(1),
-char(17),char(0),char(90),char(1),char(17),char(0),char(91),char(1),char(13),char(0),char(82),char(1),char(13),char(0),char(92),char(1),char(13),char(0),char(93),char(1),
-char(13),char(0),char(94),char(1),char(13),char(0),char(95),char(1),char(13),char(0),char(96),char(1),char(4),char(0),char(97),char(1),char(7),char(0),char(98),char(1),
-char(4),char(0),char(99),char(1),char(4),char(0),char(100),char(1),char(4),char(0),char(101),char(1),char(7),char(0),char(102),char(1),char(7),char(0),char(103),char(1),
-char(4),char(0),char(104),char(1),char(4),char(0),char(105),char(1),char(7),char(0),char(106),char(1),char(7),char(0),char(107),char(1),char(7),char(0),char(108),char(1),
-char(7),char(0),char(109),char(1),char(7),char(0),char(110),char(1),char(7),char(0),char(111),char(1),char(4),char(0),char(112),char(1),char(4),char(0),char(113),char(1),
-char(4),char(0),char(114),char(1),char(91),char(0),char(12),char(0),char(9),char(0),char(115),char(1),char(9),char(0),char(116),char(1),char(13),char(0),char(117),char(1),
-char(7),char(0),char(118),char(1),char(7),char(0),char(-86),char(0),char(7),char(0),char(119),char(1),char(4),char(0),char(120),char(1),char(13),char(0),char(121),char(1),
-char(4),char(0),char(122),char(1),char(4),char(0),char(123),char(1),char(4),char(0),char(124),char(1),char(4),char(0),char(53),char(0),char(92),char(0),char(19),char(0),
-char(50),char(0),char(-70),char(0),char(89),char(0),char(125),char(1),char(82),char(0),char(126),char(1),char(83),char(0),char(127),char(1),char(84),char(0),char(-128),char(1),
-char(85),char(0),char(-127),char(1),char(86),char(0),char(-126),char(1),char(87),char(0),char(-125),char(1),char(90),char(0),char(-124),char(1),char(91),char(0),char(-123),char(1),
-char(4),char(0),char(-122),char(1),char(4),char(0),char(100),char(1),char(4),char(0),char(-121),char(1),char(4),char(0),char(-120),char(1),char(4),char(0),char(-119),char(1),
-char(4),char(0),char(-118),char(1),char(4),char(0),char(-117),char(1),char(4),char(0),char(-116),char(1),char(88),char(0),char(-115),char(1),char(93),char(0),char(28),char(0),
-char(16),char(0),char(-114),char(1),char(14),char(0),char(-113),char(1),char(14),char(0),char(-112),char(1),char(14),char(0),char(-111),char(1),char(14),char(0),char(-110),char(1),
-char(14),char(0),char(-109),char(1),char(14),char(0),char(-108),char(1),char(14),char(0),char(-107),char(1),char(14),char(0),char(-106),char(1),char(14),char(0),char(-105),char(1),
-char(8),char(0),char(-104),char(1),char(4),char(0),char(-103),char(1),char(4),char(0),char(124),char(1),char(4),char(0),char(-102),char(1),char(4),char(0),char(-101),char(1),
-char(8),char(0),char(-100),char(1),char(8),char(0),char(-99),char(1),char(8),char(0),char(-98),char(1),char(8),char(0),char(-97),char(1),char(8),char(0),char(-96),char(1),
-char(8),char(0),char(-95),char(1),char(8),char(0),char(-94),char(1),char(8),char(0),char(-93),char(1),char(8),char(0),char(-92),char(1),char(0),char(0),char(-91),char(1),
-char(0),char(0),char(-90),char(1),char(48),char(0),char(-89),char(1),char(0),char(0),char(-88),char(1),char(94),char(0),char(28),char(0),char(15),char(0),char(-114),char(1),
-char(13),char(0),char(-113),char(1),char(13),char(0),char(-112),char(1),char(13),char(0),char(-111),char(1),char(13),char(0),char(-110),char(1),char(13),char(0),char(-109),char(1),
-char(13),char(0),char(-108),char(1),char(13),char(0),char(-107),char(1),char(13),char(0),char(-106),char(1),char(13),char(0),char(-105),char(1),char(4),char(0),char(-102),char(1),
-char(7),char(0),char(-104),char(1),char(4),char(0),char(-103),char(1),char(4),char(0),char(124),char(1),char(7),char(0),char(-100),char(1),char(7),char(0),char(-99),char(1),
-char(7),char(0),char(-98),char(1),char(4),char(0),char(-101),char(1),char(7),char(0),char(-97),char(1),char(7),char(0),char(-96),char(1),char(7),char(0),char(-95),char(1),
-char(7),char(0),char(-94),char(1),char(7),char(0),char(-93),char(1),char(7),char(0),char(-92),char(1),char(0),char(0),char(-91),char(1),char(0),char(0),char(-90),char(1),
-char(50),char(0),char(-89),char(1),char(0),char(0),char(-88),char(1),char(95),char(0),char(11),char(0),char(14),char(0),char(-87),char(1),char(16),char(0),char(-86),char(1),
-char(14),char(0),char(-85),char(1),char(14),char(0),char(-84),char(1),char(14),char(0),char(-83),char(1),char(8),char(0),char(-82),char(1),char(4),char(0),char(-121),char(1),
-char(0),char(0),char(37),char(0),char(0),char(0),char(-81),char(1),char(93),char(0),char(-128),char(1),char(48),char(0),char(-80),char(1),char(96),char(0),char(10),char(0),
-char(13),char(0),char(-87),char(1),char(15),char(0),char(-86),char(1),char(13),char(0),char(-85),char(1),char(13),char(0),char(-84),char(1),char(13),char(0),char(-83),char(1),
-char(7),char(0),char(-82),char(1),char(4),char(0),char(-121),char(1),char(0),char(0),char(-81),char(1),char(94),char(0),char(-128),char(1),char(50),char(0),char(-80),char(1),
-char(97),char(0),char(4),char(0),char(50),char(0),char(-79),char(1),char(96),char(0),char(-78),char(1),char(4),char(0),char(-77),char(1),char(0),char(0),char(37),char(0),
-char(98),char(0),char(4),char(0),char(48),char(0),char(-79),char(1),char(95),char(0),char(-78),char(1),char(4),char(0),char(-77),char(1),char(0),char(0),char(37),char(0),
-};
+char(7),char(0),char(-81),char(0),char(7),char(0),char(-80),char(0),char(7),char(0),char(-79),char(0),char(7),char(0),char(-78),char(0),char(7),char(0),char(-77),char(0),
+char(7),char(0),char(-76),char(0),char(4),char(0),char(-75),char(0),char(4),char(0),char(-74),char(0),char(4),char(0),char(-73),char(0),char(4),char(0),char(-72),char(0),
+char(4),char(0),char(-71),char(0),char(55),char(0),char(2),char(0),char(53),char(0),char(-70),char(0),char(14),char(0),char(-69),char(0),char(56),char(0),char(2),char(0),
+char(54),char(0),char(-70),char(0),char(13),char(0),char(-69),char(0),char(57),char(0),char(21),char(0),char(50),char(0),char(-68),char(0),char(17),char(0),char(-67),char(0),
+char(13),char(0),char(-66),char(0),char(13),char(0),char(-65),char(0),char(13),char(0),char(-64),char(0),char(13),char(0),char(-63),char(0),char(13),char(0),char(-69),char(0),
+char(13),char(0),char(-62),char(0),char(13),char(0),char(-61),char(0),char(13),char(0),char(-60),char(0),char(13),char(0),char(-59),char(0),char(7),char(0),char(-58),char(0),
+char(7),char(0),char(-57),char(0),char(7),char(0),char(-56),char(0),char(7),char(0),char(-55),char(0),char(7),char(0),char(-54),char(0),char(7),char(0),char(-53),char(0),
+char(7),char(0),char(-52),char(0),char(7),char(0),char(-51),char(0),char(7),char(0),char(-50),char(0),char(4),char(0),char(-49),char(0),char(58),char(0),char(22),char(0),
+char(48),char(0),char(-68),char(0),char(18),char(0),char(-67),char(0),char(14),char(0),char(-66),char(0),char(14),char(0),char(-65),char(0),char(14),char(0),char(-64),char(0),
+char(14),char(0),char(-63),char(0),char(14),char(0),char(-69),char(0),char(14),char(0),char(-62),char(0),char(14),char(0),char(-61),char(0),char(14),char(0),char(-60),char(0),
+char(14),char(0),char(-59),char(0),char(8),char(0),char(-58),char(0),char(8),char(0),char(-57),char(0),char(8),char(0),char(-56),char(0),char(8),char(0),char(-55),char(0),
+char(8),char(0),char(-54),char(0),char(8),char(0),char(-53),char(0),char(8),char(0),char(-52),char(0),char(8),char(0),char(-51),char(0),char(8),char(0),char(-50),char(0),
+char(4),char(0),char(-49),char(0),char(0),char(0),char(37),char(0),char(59),char(0),char(2),char(0),char(4),char(0),char(-48),char(0),char(4),char(0),char(-47),char(0),
+char(60),char(0),char(13),char(0),char(57),char(0),char(-46),char(0),char(57),char(0),char(-45),char(0),char(0),char(0),char(35),char(0),char(4),char(0),char(-127),char(0),
+char(4),char(0),char(-44),char(0),char(4),char(0),char(-43),char(0),char(4),char(0),char(-42),char(0),char(7),char(0),char(-41),char(0),char(7),char(0),char(-40),char(0),
+char(4),char(0),char(-39),char(0),char(4),char(0),char(-38),char(0),char(7),char(0),char(-37),char(0),char(4),char(0),char(-36),char(0),char(61),char(0),char(13),char(0),
+char(62),char(0),char(-46),char(0),char(62),char(0),char(-45),char(0),char(0),char(0),char(35),char(0),char(4),char(0),char(-127),char(0),char(4),char(0),char(-44),char(0),
+char(4),char(0),char(-43),char(0),char(4),char(0),char(-42),char(0),char(7),char(0),char(-41),char(0),char(7),char(0),char(-40),char(0),char(4),char(0),char(-39),char(0),
+char(4),char(0),char(-38),char(0),char(7),char(0),char(-37),char(0),char(4),char(0),char(-36),char(0),char(63),char(0),char(14),char(0),char(58),char(0),char(-46),char(0),
+char(58),char(0),char(-45),char(0),char(0),char(0),char(35),char(0),char(4),char(0),char(-127),char(0),char(4),char(0),char(-44),char(0),char(4),char(0),char(-43),char(0),
+char(4),char(0),char(-42),char(0),char(8),char(0),char(-41),char(0),char(8),char(0),char(-40),char(0),char(4),char(0),char(-39),char(0),char(4),char(0),char(-38),char(0),
+char(8),char(0),char(-37),char(0),char(4),char(0),char(-36),char(0),char(0),char(0),char(-35),char(0),char(64),char(0),char(3),char(0),char(61),char(0),char(-34),char(0),
+char(13),char(0),char(-33),char(0),char(13),char(0),char(-32),char(0),char(65),char(0),char(3),char(0),char(63),char(0),char(-34),char(0),char(14),char(0),char(-33),char(0),
+char(14),char(0),char(-32),char(0),char(66),char(0),char(3),char(0),char(61),char(0),char(-34),char(0),char(14),char(0),char(-33),char(0),char(14),char(0),char(-32),char(0),
+char(67),char(0),char(13),char(0),char(61),char(0),char(-34),char(0),char(20),char(0),char(-31),char(0),char(20),char(0),char(-30),char(0),char(4),char(0),char(-29),char(0),
+char(4),char(0),char(-28),char(0),char(4),char(0),char(-27),char(0),char(7),char(0),char(-26),char(0),char(7),char(0),char(-25),char(0),char(7),char(0),char(-24),char(0),
+char(7),char(0),char(-23),char(0),char(7),char(0),char(-22),char(0),char(7),char(0),char(-21),char(0),char(7),char(0),char(-20),char(0),char(68),char(0),char(13),char(0),
+char(61),char(0),char(-34),char(0),char(19),char(0),char(-31),char(0),char(19),char(0),char(-30),char(0),char(4),char(0),char(-29),char(0),char(4),char(0),char(-28),char(0),
+char(4),char(0),char(-27),char(0),char(7),char(0),char(-26),char(0),char(7),char(0),char(-25),char(0),char(7),char(0),char(-24),char(0),char(7),char(0),char(-23),char(0),
+char(7),char(0),char(-22),char(0),char(7),char(0),char(-21),char(0),char(7),char(0),char(-20),char(0),char(69),char(0),char(14),char(0),char(63),char(0),char(-34),char(0),
+char(20),char(0),char(-31),char(0),char(20),char(0),char(-30),char(0),char(4),char(0),char(-29),char(0),char(4),char(0),char(-28),char(0),char(4),char(0),char(-27),char(0),
+char(8),char(0),char(-26),char(0),char(8),char(0),char(-25),char(0),char(8),char(0),char(-24),char(0),char(8),char(0),char(-23),char(0),char(8),char(0),char(-22),char(0),
+char(8),char(0),char(-21),char(0),char(8),char(0),char(-20),char(0),char(0),char(0),char(-19),char(0),char(70),char(0),char(10),char(0),char(63),char(0),char(-34),char(0),
+char(20),char(0),char(-31),char(0),char(20),char(0),char(-30),char(0),char(8),char(0),char(-18),char(0),char(8),char(0),char(-17),char(0),char(8),char(0),char(-16),char(0),
+char(8),char(0),char(-22),char(0),char(8),char(0),char(-21),char(0),char(8),char(0),char(-20),char(0),char(8),char(0),char(-89),char(0),char(71),char(0),char(11),char(0),
+char(61),char(0),char(-34),char(0),char(19),char(0),char(-31),char(0),char(19),char(0),char(-30),char(0),char(7),char(0),char(-18),char(0),char(7),char(0),char(-17),char(0),
+char(7),char(0),char(-16),char(0),char(7),char(0),char(-22),char(0),char(7),char(0),char(-21),char(0),char(7),char(0),char(-20),char(0),char(7),char(0),char(-89),char(0),
+char(0),char(0),char(21),char(0),char(72),char(0),char(9),char(0),char(61),char(0),char(-34),char(0),char(19),char(0),char(-31),char(0),char(19),char(0),char(-30),char(0),
+char(13),char(0),char(-15),char(0),char(13),char(0),char(-14),char(0),char(13),char(0),char(-13),char(0),char(13),char(0),char(-12),char(0),char(4),char(0),char(-11),char(0),
+char(4),char(0),char(-10),char(0),char(73),char(0),char(9),char(0),char(63),char(0),char(-34),char(0),char(20),char(0),char(-31),char(0),char(20),char(0),char(-30),char(0),
+char(14),char(0),char(-15),char(0),char(14),char(0),char(-14),char(0),char(14),char(0),char(-13),char(0),char(14),char(0),char(-12),char(0),char(4),char(0),char(-11),char(0),
+char(4),char(0),char(-10),char(0),char(74),char(0),char(5),char(0),char(72),char(0),char(-9),char(0),char(4),char(0),char(-8),char(0),char(7),char(0),char(-7),char(0),
+char(7),char(0),char(-6),char(0),char(7),char(0),char(-5),char(0),char(75),char(0),char(5),char(0),char(73),char(0),char(-9),char(0),char(4),char(0),char(-8),char(0),
+char(8),char(0),char(-7),char(0),char(8),char(0),char(-6),char(0),char(8),char(0),char(-5),char(0),char(76),char(0),char(41),char(0),char(61),char(0),char(-34),char(0),
+char(19),char(0),char(-31),char(0),char(19),char(0),char(-30),char(0),char(13),char(0),char(-15),char(0),char(13),char(0),char(-14),char(0),char(13),char(0),char(-4),char(0),
+char(13),char(0),char(-3),char(0),char(13),char(0),char(-2),char(0),char(13),char(0),char(-1),char(0),char(13),char(0),char(0),char(1),char(13),char(0),char(1),char(1),
+char(13),char(0),char(2),char(1),char(13),char(0),char(3),char(1),char(13),char(0),char(4),char(1),char(13),char(0),char(5),char(1),char(13),char(0),char(6),char(1),
+char(0),char(0),char(7),char(1),char(0),char(0),char(8),char(1),char(0),char(0),char(9),char(1),char(0),char(0),char(10),char(1),char(0),char(0),char(11),char(1),
+char(0),char(0),char(-19),char(0),char(13),char(0),char(-13),char(0),char(13),char(0),char(-12),char(0),char(13),char(0),char(12),char(1),char(13),char(0),char(13),char(1),
+char(13),char(0),char(14),char(1),char(13),char(0),char(15),char(1),char(13),char(0),char(16),char(1),char(13),char(0),char(17),char(1),char(13),char(0),char(18),char(1),
+char(13),char(0),char(19),char(1),char(13),char(0),char(20),char(1),char(13),char(0),char(21),char(1),char(13),char(0),char(22),char(1),char(0),char(0),char(23),char(1),
+char(0),char(0),char(24),char(1),char(0),char(0),char(25),char(1),char(0),char(0),char(26),char(1),char(0),char(0),char(27),char(1),char(4),char(0),char(28),char(1),
+char(77),char(0),char(41),char(0),char(63),char(0),char(-34),char(0),char(20),char(0),char(-31),char(0),char(20),char(0),char(-30),char(0),char(14),char(0),char(-15),char(0),
+char(14),char(0),char(-14),char(0),char(14),char(0),char(-4),char(0),char(14),char(0),char(-3),char(0),char(14),char(0),char(-2),char(0),char(14),char(0),char(-1),char(0),
+char(14),char(0),char(0),char(1),char(14),char(0),char(1),char(1),char(14),char(0),char(2),char(1),char(14),char(0),char(3),char(1),char(14),char(0),char(4),char(1),
+char(14),char(0),char(5),char(1),char(14),char(0),char(6),char(1),char(0),char(0),char(7),char(1),char(0),char(0),char(8),char(1),char(0),char(0),char(9),char(1),
+char(0),char(0),char(10),char(1),char(0),char(0),char(11),char(1),char(0),char(0),char(-19),char(0),char(14),char(0),char(-13),char(0),char(14),char(0),char(-12),char(0),
+char(14),char(0),char(12),char(1),char(14),char(0),char(13),char(1),char(14),char(0),char(14),char(1),char(14),char(0),char(15),char(1),char(14),char(0),char(16),char(1),
+char(14),char(0),char(17),char(1),char(14),char(0),char(18),char(1),char(14),char(0),char(19),char(1),char(14),char(0),char(20),char(1),char(14),char(0),char(21),char(1),
+char(14),char(0),char(22),char(1),char(0),char(0),char(23),char(1),char(0),char(0),char(24),char(1),char(0),char(0),char(25),char(1),char(0),char(0),char(26),char(1),
+char(0),char(0),char(27),char(1),char(4),char(0),char(28),char(1),char(78),char(0),char(9),char(0),char(61),char(0),char(-34),char(0),char(19),char(0),char(-31),char(0),
+char(19),char(0),char(-30),char(0),char(7),char(0),char(-15),char(0),char(7),char(0),char(-14),char(0),char(7),char(0),char(-13),char(0),char(7),char(0),char(-12),char(0),
+char(4),char(0),char(-11),char(0),char(4),char(0),char(-10),char(0),char(79),char(0),char(9),char(0),char(63),char(0),char(-34),char(0),char(20),char(0),char(-31),char(0),
+char(20),char(0),char(-30),char(0),char(8),char(0),char(-15),char(0),char(8),char(0),char(-14),char(0),char(8),char(0),char(-13),char(0),char(8),char(0),char(-12),char(0),
+char(4),char(0),char(-11),char(0),char(4),char(0),char(-10),char(0),char(80),char(0),char(5),char(0),char(60),char(0),char(-34),char(0),char(13),char(0),char(29),char(1),
+char(13),char(0),char(30),char(1),char(7),char(0),char(31),char(1),char(0),char(0),char(37),char(0),char(81),char(0),char(4),char(0),char(63),char(0),char(-34),char(0),
+char(14),char(0),char(29),char(1),char(14),char(0),char(30),char(1),char(8),char(0),char(31),char(1),char(82),char(0),char(4),char(0),char(7),char(0),char(32),char(1),
+char(7),char(0),char(33),char(1),char(7),char(0),char(34),char(1),char(4),char(0),char(79),char(0),char(83),char(0),char(10),char(0),char(82),char(0),char(35),char(1),
+char(13),char(0),char(36),char(1),char(13),char(0),char(37),char(1),char(13),char(0),char(38),char(1),char(13),char(0),char(39),char(1),char(13),char(0),char(40),char(1),
+char(7),char(0),char(-58),char(0),char(7),char(0),char(41),char(1),char(4),char(0),char(42),char(1),char(4),char(0),char(53),char(0),char(84),char(0),char(4),char(0),
+char(82),char(0),char(35),char(1),char(4),char(0),char(43),char(1),char(7),char(0),char(44),char(1),char(4),char(0),char(45),char(1),char(85),char(0),char(4),char(0),
+char(13),char(0),char(40),char(1),char(82),char(0),char(35),char(1),char(4),char(0),char(46),char(1),char(7),char(0),char(47),char(1),char(86),char(0),char(7),char(0),
+char(13),char(0),char(48),char(1),char(82),char(0),char(35),char(1),char(4),char(0),char(49),char(1),char(7),char(0),char(50),char(1),char(7),char(0),char(51),char(1),
+char(7),char(0),char(52),char(1),char(4),char(0),char(53),char(0),char(87),char(0),char(6),char(0),char(17),char(0),char(53),char(1),char(13),char(0),char(51),char(1),
+char(13),char(0),char(54),char(1),char(62),char(0),char(55),char(1),char(4),char(0),char(56),char(1),char(7),char(0),char(52),char(1),char(88),char(0),char(26),char(0),
+char(4),char(0),char(57),char(1),char(7),char(0),char(58),char(1),char(7),char(0),char(-89),char(0),char(7),char(0),char(59),char(1),char(7),char(0),char(60),char(1),
+char(7),char(0),char(61),char(1),char(7),char(0),char(62),char(1),char(7),char(0),char(63),char(1),char(7),char(0),char(64),char(1),char(7),char(0),char(65),char(1),
+char(7),char(0),char(66),char(1),char(7),char(0),char(67),char(1),char(7),char(0),char(68),char(1),char(7),char(0),char(69),char(1),char(7),char(0),char(70),char(1),
+char(7),char(0),char(71),char(1),char(7),char(0),char(72),char(1),char(7),char(0),char(73),char(1),char(7),char(0),char(74),char(1),char(7),char(0),char(75),char(1),
+char(7),char(0),char(76),char(1),char(4),char(0),char(77),char(1),char(4),char(0),char(78),char(1),char(4),char(0),char(79),char(1),char(4),char(0),char(80),char(1),
+char(4),char(0),char(-99),char(0),char(89),char(0),char(12),char(0),char(17),char(0),char(81),char(1),char(17),char(0),char(82),char(1),char(17),char(0),char(83),char(1),
+char(13),char(0),char(84),char(1),char(13),char(0),char(85),char(1),char(7),char(0),char(86),char(1),char(4),char(0),char(87),char(1),char(4),char(0),char(88),char(1),
+char(4),char(0),char(89),char(1),char(4),char(0),char(90),char(1),char(7),char(0),char(50),char(1),char(4),char(0),char(53),char(0),char(90),char(0),char(27),char(0),
+char(19),char(0),char(91),char(1),char(17),char(0),char(92),char(1),char(17),char(0),char(93),char(1),char(13),char(0),char(84),char(1),char(13),char(0),char(94),char(1),
+char(13),char(0),char(95),char(1),char(13),char(0),char(96),char(1),char(13),char(0),char(97),char(1),char(13),char(0),char(98),char(1),char(4),char(0),char(99),char(1),
+char(7),char(0),char(100),char(1),char(4),char(0),char(101),char(1),char(4),char(0),char(102),char(1),char(4),char(0),char(103),char(1),char(7),char(0),char(104),char(1),
+char(7),char(0),char(105),char(1),char(4),char(0),char(106),char(1),char(4),char(0),char(107),char(1),char(7),char(0),char(108),char(1),char(7),char(0),char(109),char(1),
+char(7),char(0),char(110),char(1),char(7),char(0),char(111),char(1),char(7),char(0),char(112),char(1),char(7),char(0),char(113),char(1),char(4),char(0),char(114),char(1),
+char(4),char(0),char(115),char(1),char(4),char(0),char(116),char(1),char(91),char(0),char(12),char(0),char(9),char(0),char(117),char(1),char(9),char(0),char(118),char(1),
+char(13),char(0),char(119),char(1),char(7),char(0),char(120),char(1),char(7),char(0),char(-85),char(0),char(7),char(0),char(121),char(1),char(4),char(0),char(122),char(1),
+char(13),char(0),char(123),char(1),char(4),char(0),char(124),char(1),char(4),char(0),char(125),char(1),char(4),char(0),char(126),char(1),char(4),char(0),char(53),char(0),
+char(92),char(0),char(19),char(0),char(50),char(0),char(-68),char(0),char(89),char(0),char(127),char(1),char(82),char(0),char(-128),char(1),char(83),char(0),char(-127),char(1),
+char(84),char(0),char(-126),char(1),char(85),char(0),char(-125),char(1),char(86),char(0),char(-124),char(1),char(87),char(0),char(-123),char(1),char(90),char(0),char(-122),char(1),
+char(91),char(0),char(-121),char(1),char(4),char(0),char(-120),char(1),char(4),char(0),char(102),char(1),char(4),char(0),char(-119),char(1),char(4),char(0),char(-118),char(1),
+char(4),char(0),char(-117),char(1),char(4),char(0),char(-116),char(1),char(4),char(0),char(-115),char(1),char(4),char(0),char(-114),char(1),char(88),char(0),char(-113),char(1),
+char(93),char(0),char(28),char(0),char(16),char(0),char(-112),char(1),char(14),char(0),char(-111),char(1),char(14),char(0),char(-110),char(1),char(14),char(0),char(-109),char(1),
+char(14),char(0),char(-108),char(1),char(14),char(0),char(-107),char(1),char(14),char(0),char(-106),char(1),char(14),char(0),char(-105),char(1),char(14),char(0),char(-104),char(1),
+char(14),char(0),char(-103),char(1),char(8),char(0),char(-102),char(1),char(4),char(0),char(-101),char(1),char(4),char(0),char(126),char(1),char(4),char(0),char(-100),char(1),
+char(4),char(0),char(-99),char(1),char(8),char(0),char(-98),char(1),char(8),char(0),char(-97),char(1),char(8),char(0),char(-96),char(1),char(8),char(0),char(-95),char(1),
+char(8),char(0),char(-94),char(1),char(8),char(0),char(-93),char(1),char(8),char(0),char(-92),char(1),char(8),char(0),char(-91),char(1),char(8),char(0),char(-90),char(1),
+char(0),char(0),char(-89),char(1),char(0),char(0),char(-88),char(1),char(48),char(0),char(-87),char(1),char(0),char(0),char(-86),char(1),char(94),char(0),char(28),char(0),
+char(15),char(0),char(-112),char(1),char(13),char(0),char(-111),char(1),char(13),char(0),char(-110),char(1),char(13),char(0),char(-109),char(1),char(13),char(0),char(-108),char(1),
+char(13),char(0),char(-107),char(1),char(13),char(0),char(-106),char(1),char(13),char(0),char(-105),char(1),char(13),char(0),char(-104),char(1),char(13),char(0),char(-103),char(1),
+char(4),char(0),char(-100),char(1),char(7),char(0),char(-102),char(1),char(4),char(0),char(-101),char(1),char(4),char(0),char(126),char(1),char(7),char(0),char(-98),char(1),
+char(7),char(0),char(-97),char(1),char(7),char(0),char(-96),char(1),char(4),char(0),char(-99),char(1),char(7),char(0),char(-95),char(1),char(7),char(0),char(-94),char(1),
+char(7),char(0),char(-93),char(1),char(7),char(0),char(-92),char(1),char(7),char(0),char(-91),char(1),char(7),char(0),char(-90),char(1),char(0),char(0),char(-89),char(1),
+char(0),char(0),char(-88),char(1),char(50),char(0),char(-87),char(1),char(0),char(0),char(-86),char(1),char(95),char(0),char(11),char(0),char(14),char(0),char(-85),char(1),
+char(16),char(0),char(-84),char(1),char(14),char(0),char(-83),char(1),char(14),char(0),char(-82),char(1),char(14),char(0),char(-81),char(1),char(8),char(0),char(-80),char(1),
+char(4),char(0),char(-119),char(1),char(0),char(0),char(37),char(0),char(0),char(0),char(-79),char(1),char(93),char(0),char(-126),char(1),char(48),char(0),char(-78),char(1),
+char(96),char(0),char(10),char(0),char(13),char(0),char(-85),char(1),char(15),char(0),char(-84),char(1),char(13),char(0),char(-83),char(1),char(13),char(0),char(-82),char(1),
+char(13),char(0),char(-81),char(1),char(7),char(0),char(-80),char(1),char(4),char(0),char(-119),char(1),char(0),char(0),char(-79),char(1),char(94),char(0),char(-126),char(1),
+char(50),char(0),char(-78),char(1),char(97),char(0),char(4),char(0),char(50),char(0),char(-77),char(1),char(96),char(0),char(-76),char(1),char(4),char(0),char(-75),char(1),
+char(0),char(0),char(37),char(0),char(98),char(0),char(4),char(0),char(48),char(0),char(-77),char(1),char(95),char(0),char(-76),char(1),char(4),char(0),char(-75),char(1),
+char(0),char(0),char(37),char(0),};
int sBulletDNAlen64= sizeof(sBulletDNAstr64);
-// clang-format on
diff --git a/thirdparty/enet/LICENSE b/thirdparty/enet/LICENSE
index 39af84a8f6..78d9dcf613 100644
--- a/thirdparty/enet/LICENSE
+++ b/thirdparty/enet/LICENSE
@@ -1,4 +1,4 @@
-Copyright (c) 2002-2016 Lee Salzman
+Copyright (c) 2002-2019 Lee Salzman
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:
diff --git a/thirdparty/enet/enet/enet.h b/thirdparty/enet/enet/enet.h
index 246cbb0a62..966e3a465d 100644
--- a/thirdparty/enet/enet/enet.h
+++ b/thirdparty/enet/enet/enet.h
@@ -22,7 +22,7 @@ extern "C"
#define ENET_VERSION_MAJOR 1
#define ENET_VERSION_MINOR 3
-#define ENET_VERSION_PATCH 13
+#define ENET_VERSION_PATCH 14
#define ENET_VERSION_CREATE(major, minor, patch) (((major)<<16) | ((minor)<<8) | (patch))
#define ENET_VERSION_GET_MAJOR(version) (((version)>>16)&0xFF)
#define ENET_VERSION_GET_MINOR(version) (((version)>>8)&0xFF)
@@ -507,6 +507,17 @@ ENET_API int enet_socketset_select (ENetSocket, ENetSocketSet *, ENetSock
/** @defgroup Address ENet address functions
@{
*/
+
+/** Attempts to parse the printable form of the IP address in the parameter hostName
+ and sets the host field in the address parameter if successful.
+ @param address destination to store the parsed IP address
+ @param hostName IP address to parse
+ @retval 0 on success
+ @retval < 0 on failure
+ @returns the address of the given hostName in address on success
+*/
+ENET_API int enet_address_set_host_ip (ENetAddress * address, const char * hostName);
+
/** Attempts to resolve the host named by the parameter hostName and sets
the host field in the address parameter if successful.
@param address destination to store resolved address
diff --git a/thirdparty/enet/patches/ipv6_support.patch b/thirdparty/enet/patches/ipv6_support.patch
new file mode 100644
index 0000000000..1f79863645
--- /dev/null
+++ b/thirdparty/enet/patches/ipv6_support.patch
@@ -0,0 +1,105 @@
+diff --git a/thirdparty/enet/enet/enet.h b/thirdparty/enet/enet/enet.h
+index 650b199ee5..246cbb0a62 100644
+--- a/thirdparty/enet/enet/enet.h
++++ b/thirdparty/enet/enet/enet.h
+@@ -10,13 +10,10 @@ extern "C"
+ {
+ #endif
+
++#include <stdint.h>
+ #include <stdlib.h>
+
+-#ifdef _WIN32
+-#include "enet/win32.h"
+-#else
+-#include "enet/unix.h"
+-#endif
++#include "enet/godot.h"
+
+ #include "enet/types.h"
+ #include "enet/protocol.h"
+@@ -72,7 +69,6 @@ typedef enum _ENetSocketShutdown
+ ENET_SOCKET_SHUTDOWN_READ_WRITE = 2
+ } ENetSocketShutdown;
+
+-#define ENET_HOST_ANY 0
+ #define ENET_HOST_BROADCAST 0xFFFFFFFFU
+ #define ENET_PORT_ANY 0
+
+@@ -88,9 +84,11 @@ typedef enum _ENetSocketShutdown
+ */
+ typedef struct _ENetAddress
+ {
+- enet_uint32 host;
++ uint8_t host[16];
+ enet_uint16 port;
++ uint8_t wildcard;
+ } ENetAddress;
++#define enet_host_equal(host_a, host_b) (memcmp(&host_a, &host_b,16) == 0)
+
+ /**
+ * Packet flag bit constants.
+@@ -519,6 +517,16 @@ ENET_API int enet_socketset_select (ENetSocket, ENetSocketSet *, ENetSock
+ */
+ ENET_API int enet_address_set_host (ENetAddress * address, const char * hostName);
+
++/** Sets the host field in the address parameter from ip struct.
++ @param address destination to store resolved address
++ @param ip the ip struct to read from
++ @param size the size of the ip struct.
++ @retval 0 on success
++ @retval != 0 on failure
++ @returns the address of the given ip in address on success.
++*/
++ENET_API void enet_address_set_ip(ENetAddress * address, const uint8_t * ip, size_t size);
++
+ /** Gives the printable form of the IP address specified in the address parameter.
+ @param address address printed
+ @param hostName destination for name, must not be NULL
+diff --git a/thirdparty/enet/host.c b/thirdparty/enet/host.c
+index 3be6c0922c..fc4da4ca67 100644
+--- a/thirdparty/enet/host.c
++++ b/thirdparty/enet/host.c
+@@ -87,7 +87,7 @@ enet_host_create (const ENetAddress * address, size_t peerCount, size_t channelL
+ host -> commandCount = 0;
+ host -> bufferCount = 0;
+ host -> checksum = NULL;
+- host -> receivedAddress.host = ENET_HOST_ANY;
++ memset(host -> receivedAddress.host, 0, 16);
+ host -> receivedAddress.port = 0;
+ host -> receivedData = NULL;
+ host -> receivedDataLength = 0;
+diff --git a/thirdparty/enet/protocol.c b/thirdparty/enet/protocol.c
+index 29d648732d..ab26886de4 100644
+--- a/thirdparty/enet/protocol.c
++++ b/thirdparty/enet/protocol.c
+@@ -298,7 +298,7 @@ enet_protocol_handle_connect (ENetHost * host, ENetProtocolHeader * header, ENet
+ }
+ else
+ if (currentPeer -> state != ENET_PEER_STATE_CONNECTING &&
+- currentPeer -> address.host == host -> receivedAddress.host)
++ enet_host_equal(currentPeer -> address.host, host -> receivedAddress.host))
+ {
+ if (currentPeer -> address.port == host -> receivedAddress.port &&
+ currentPeer -> connectID == command -> connect.connectID)
+@@ -1010,9 +1010,8 @@ enet_protocol_handle_incoming_commands (ENetHost * host, ENetEvent * event)
+
+ if (peer -> state == ENET_PEER_STATE_DISCONNECTED ||
+ peer -> state == ENET_PEER_STATE_ZOMBIE ||
+- ((host -> receivedAddress.host != peer -> address.host ||
+- host -> receivedAddress.port != peer -> address.port) &&
+- peer -> address.host != ENET_HOST_BROADCAST) ||
++ (!enet_host_equal(host -> receivedAddress.host, peer -> address.host) ||
++ host -> receivedAddress.port != peer -> address.port) ||
+ (peer -> outgoingPeerID < ENET_PROTOCOL_MAXIMUM_PEER_ID &&
+ sessionID != peer -> incomingSessionID))
+ return 0;
+@@ -1054,7 +1053,7 @@ enet_protocol_handle_incoming_commands (ENetHost * host, ENetEvent * event)
+
+ if (peer != NULL)
+ {
+- peer -> address.host = host -> receivedAddress.host;
++ enet_address_set_ip(&(peer -> address), host -> receivedAddress.host, 16);
+ peer -> address.port = host -> receivedAddress.port;
+ peer -> incomingDataTotal += host -> receivedDataLength;
+ }
diff --git a/thirdparty/enet/protocol.c b/thirdparty/enet/protocol.c
index cbeea1a763..28ad5fc41c 100644
--- a/thirdparty/enet/protocol.c
+++ b/thirdparty/enet/protocol.c
@@ -9,7 +9,6 @@
#include "enet/time.h"
#include "enet/enet.h"
-
static size_t commandSizes [ENET_PROTOCOL_COMMAND_COUNT] =
{
0,
@@ -164,7 +163,10 @@ enet_protocol_remove_sent_unreliable_commands (ENetPeer * peer)
{
ENetOutgoingCommand * outgoingCommand;
- while (! enet_list_empty (& peer -> sentUnreliableCommands))
+ if (enet_list_empty (& peer -> sentUnreliableCommands))
+ return;
+
+ do
{
outgoingCommand = (ENetOutgoingCommand *) enet_list_front (& peer -> sentUnreliableCommands);
@@ -183,7 +185,13 @@ enet_protocol_remove_sent_unreliable_commands (ENetPeer * peer)
}
enet_free (outgoingCommand);
- }
+ } while (! enet_list_empty (& peer -> sentUnreliableCommands));
+
+ if (peer -> state == ENET_PEER_STATE_DISCONNECT_LATER &&
+ enet_list_empty (& peer -> outgoingReliableCommands) &&
+ enet_list_empty (& peer -> outgoingUnreliableCommands) &&
+ enet_list_empty (& peer -> sentReliableCommands))
+ enet_peer_disconnect (peer, peer -> eventData);
}
static ENetProtocolCommand
@@ -1406,7 +1414,8 @@ enet_protocol_send_unreliable_outgoing_commands (ENetHost * host, ENetPeer * pee
if (peer -> state == ENET_PEER_STATE_DISCONNECT_LATER &&
enet_list_empty (& peer -> outgoingReliableCommands) &&
enet_list_empty (& peer -> outgoingUnreliableCommands) &&
- enet_list_empty (& peer -> sentReliableCommands))
+ enet_list_empty (& peer -> sentReliableCommands) &&
+ enet_list_empty (& peer -> sentUnreliableCommands))
enet_peer_disconnect (peer, peer -> eventData);
}
@@ -1691,7 +1700,7 @@ enet_protocol_send_outgoing_commands (ENetHost * host, ENetEvent * event, int ch
& host -> buffers [1], host -> bufferCount - 1,
originalSize,
host -> packetData [1],
- originalSize);
+ originalSize);
if (compressedSize > 0 && compressedSize < originalSize)
{
host -> headerFlags |= ENET_PROTOCOL_HEADER_FLAG_COMPRESSED;
diff --git a/thirdparty/libwebp/src/dec/frame_dec.c b/thirdparty/libwebp/src/dec/frame_dec.c
index bda9e1a6f6..04609a8e56 100644
--- a/thirdparty/libwebp/src/dec/frame_dec.c
+++ b/thirdparty/libwebp/src/dec/frame_dec.c
@@ -732,7 +732,7 @@ static int AllocateMemory(VP8Decoder* const dec) {
mem += f_info_size;
dec->thread_ctx_.id_ = 0;
dec->thread_ctx_.f_info_ = dec->f_info_;
- if (dec->mt_method_ > 0) {
+ if (dec->filter_type_ > 0 && dec->mt_method_ > 0) {
// secondary cache line. The deblocking process need to make use of the
// filtering strength from previous macroblock row, while the new ones
// are being decoded in parallel. We'll just swap the pointers.
diff --git a/thirdparty/libwebp/src/dec/idec_dec.c b/thirdparty/libwebp/src/dec/idec_dec.c
index 9bc9166808..9035df5659 100644
--- a/thirdparty/libwebp/src/dec/idec_dec.c
+++ b/thirdparty/libwebp/src/dec/idec_dec.c
@@ -166,9 +166,11 @@ static int AppendToMemBuffer(WebPIDecoder* const idec,
VP8Decoder* const dec = (VP8Decoder*)idec->dec_;
MemBuffer* const mem = &idec->mem_;
const int need_compressed_alpha = NeedCompressedAlpha(idec);
- const uint8_t* const old_start = mem->buf_ + mem->start_;
+ const uint8_t* const old_start =
+ (mem->buf_ == NULL) ? NULL : mem->buf_ + mem->start_;
const uint8_t* const old_base =
need_compressed_alpha ? dec->alpha_data_ : old_start;
+ assert(mem->buf_ != NULL || mem->start_ == 0);
assert(mem->mode_ == MEM_MODE_APPEND);
if (data_size > MAX_CHUNK_PAYLOAD) {
// security safeguard: trying to allocate more than what the format
@@ -184,7 +186,7 @@ static int AppendToMemBuffer(WebPIDecoder* const idec,
uint8_t* const new_buf =
(uint8_t*)WebPSafeMalloc(extra_size, sizeof(*new_buf));
if (new_buf == NULL) return 0;
- memcpy(new_buf, old_base, current_size);
+ if (old_base != NULL) memcpy(new_buf, old_base, current_size);
WebPSafeFree(mem->buf_);
mem->buf_ = new_buf;
mem->buf_size_ = (size_t)extra_size;
@@ -192,6 +194,7 @@ static int AppendToMemBuffer(WebPIDecoder* const idec,
mem->end_ = current_size;
}
+ assert(mem->buf_ != NULL);
memcpy(mem->buf_ + mem->end_, data, data_size);
mem->end_ += data_size;
assert(mem->end_ <= mem->buf_size_);
@@ -204,7 +207,9 @@ static int RemapMemBuffer(WebPIDecoder* const idec,
const uint8_t* const data, size_t data_size) {
MemBuffer* const mem = &idec->mem_;
const uint8_t* const old_buf = mem->buf_;
- const uint8_t* const old_start = old_buf + mem->start_;
+ const uint8_t* const old_start =
+ (old_buf == NULL) ? NULL : old_buf + mem->start_;
+ assert(old_buf != NULL || mem->start_ == 0);
assert(mem->mode_ == MEM_MODE_MAP);
if (data_size < mem->buf_size_) return 0; // can't remap to a shorter buffer!
diff --git a/thirdparty/libwebp/src/dec/vp8i_dec.h b/thirdparty/libwebp/src/dec/vp8i_dec.h
index 3de8d86f90..600a684410 100644
--- a/thirdparty/libwebp/src/dec/vp8i_dec.h
+++ b/thirdparty/libwebp/src/dec/vp8i_dec.h
@@ -31,8 +31,8 @@ extern "C" {
// version numbers
#define DEC_MAJ_VERSION 1
-#define DEC_MIN_VERSION 0
-#define DEC_REV_VERSION 3
+#define DEC_MIN_VERSION 1
+#define DEC_REV_VERSION 0
// YUV-cache parameters. Cache is 32-bytes wide (= one cacheline).
// Constraints are: We need to store one 16x16 block of luma samples (y),
diff --git a/thirdparty/libwebp/src/dec/vp8l_dec.c b/thirdparty/libwebp/src/dec/vp8l_dec.c
index d3e27119ea..93615d4ed2 100644
--- a/thirdparty/libwebp/src/dec/vp8l_dec.c
+++ b/thirdparty/libwebp/src/dec/vp8l_dec.c
@@ -754,11 +754,11 @@ static WEBP_INLINE HTreeGroup* GetHtreeGroupForPos(VP8LMetadata* const hdr,
typedef void (*ProcessRowsFunc)(VP8LDecoder* const dec, int row);
-static void ApplyInverseTransforms(VP8LDecoder* const dec, int num_rows,
+static void ApplyInverseTransforms(VP8LDecoder* const dec,
+ int start_row, int num_rows,
const uint32_t* const rows) {
int n = dec->next_transform_;
const int cache_pixs = dec->width_ * num_rows;
- const int start_row = dec->last_row_;
const int end_row = start_row + num_rows;
const uint32_t* rows_in = rows;
uint32_t* const rows_out = dec->argb_cache_;
@@ -789,8 +789,7 @@ static void ProcessRows(VP8LDecoder* const dec, int row) {
VP8Io* const io = dec->io_;
uint8_t* rows_data = (uint8_t*)dec->argb_cache_;
const int in_stride = io->width * sizeof(uint32_t); // in unit of RGBA
-
- ApplyInverseTransforms(dec, num_rows, rows);
+ ApplyInverseTransforms(dec, dec->last_row_, num_rows, rows);
if (!SetCropWindow(io, dec->last_row_, row, &rows_data, in_stride)) {
// Nothing to output (this time).
} else {
@@ -1193,6 +1192,7 @@ static int DecodeImageData(VP8LDecoder* const dec, uint32_t* const data,
VP8LFillBitWindow(br);
dist_code = GetCopyDistance(dist_symbol, br);
dist = PlaneCodeToDistance(width, dist_code);
+
if (VP8LIsEndOfStream(br)) break;
if (src - data < (ptrdiff_t)dist || src_end - src < (ptrdiff_t)length) {
goto Error;
@@ -1553,7 +1553,7 @@ static void ExtractAlphaRows(VP8LDecoder* const dec, int last_row) {
const int cache_pixs = width * num_rows_to_process;
uint8_t* const dst = output + width * cur_row;
const uint32_t* const src = dec->argb_cache_;
- ApplyInverseTransforms(dec, num_rows_to_process, in);
+ ApplyInverseTransforms(dec, cur_row, num_rows_to_process, in);
WebPExtractGreen(src, dst, cache_pixs);
AlphaApplyFilter(alph_dec,
cur_row, cur_row + num_rows_to_process, dst, width);
diff --git a/thirdparty/libwebp/src/dec/vp8li_dec.h b/thirdparty/libwebp/src/dec/vp8li_dec.h
index 0a4d613f99..72b2e86120 100644
--- a/thirdparty/libwebp/src/dec/vp8li_dec.h
+++ b/thirdparty/libwebp/src/dec/vp8li_dec.h
@@ -37,7 +37,7 @@ struct VP8LTransform {
int bits_; // subsampling bits defining transform window.
int xsize_; // transform window X index.
int ysize_; // transform window Y index.
- uint32_t *data_; // transform data.
+ uint32_t* data_; // transform data.
};
typedef struct {
@@ -48,23 +48,23 @@ typedef struct {
int huffman_mask_;
int huffman_subsample_bits_;
int huffman_xsize_;
- uint32_t *huffman_image_;
+ uint32_t* huffman_image_;
int num_htree_groups_;
- HTreeGroup *htree_groups_;
- HuffmanCode *huffman_tables_;
+ HTreeGroup* htree_groups_;
+ HuffmanCode* huffman_tables_;
} VP8LMetadata;
typedef struct VP8LDecoder VP8LDecoder;
struct VP8LDecoder {
VP8StatusCode status_;
VP8LDecodeState state_;
- VP8Io *io_;
+ VP8Io* io_;
- const WebPDecBuffer *output_; // shortcut to io->opaque->output
+ const WebPDecBuffer* output_; // shortcut to io->opaque->output
- uint32_t *pixels_; // Internal data: either uint8_t* for alpha
+ uint32_t* pixels_; // Internal data: either uint8_t* for alpha
// or uint32_t* for BGRA.
- uint32_t *argb_cache_; // Scratch buffer for temporary BGRA storage.
+ uint32_t* argb_cache_; // Scratch buffer for temporary BGRA storage.
VP8LBitReader br_;
int incremental_; // if true, incremental decoding is expected
@@ -86,8 +86,8 @@ struct VP8LDecoder {
// or'd bitset storing the transforms types.
uint32_t transforms_seen_;
- uint8_t *rescaler_memory; // Working memory for rescaling work.
- WebPRescaler *rescaler; // Common rescaler for all channels.
+ uint8_t* rescaler_memory; // Working memory for rescaling work.
+ WebPRescaler* rescaler; // Common rescaler for all channels.
};
//------------------------------------------------------------------------------
diff --git a/thirdparty/libwebp/src/demux/demux.c b/thirdparty/libwebp/src/demux/demux.c
index ab6433e54b..1b3cc2e0a8 100644
--- a/thirdparty/libwebp/src/demux/demux.c
+++ b/thirdparty/libwebp/src/demux/demux.c
@@ -24,8 +24,8 @@
#include "src/webp/format_constants.h"
#define DMUX_MAJ_VERSION 1
-#define DMUX_MIN_VERSION 0
-#define DMUX_REV_VERSION 3
+#define DMUX_MIN_VERSION 1
+#define DMUX_REV_VERSION 0
typedef struct {
size_t start_; // start location of the data
diff --git a/thirdparty/libwebp/src/dsp/dec_neon.c b/thirdparty/libwebp/src/dsp/dec_neon.c
index ffa697fcf9..239ec4167e 100644
--- a/thirdparty/libwebp/src/dsp/dec_neon.c
+++ b/thirdparty/libwebp/src/dsp/dec_neon.c
@@ -1361,7 +1361,8 @@ static void RD4_NEON(uint8_t* dst) { // Down-right
const uint32_t J = dst[-1 + 1 * BPS];
const uint32_t K = dst[-1 + 2 * BPS];
const uint32_t L = dst[-1 + 3 * BPS];
- const uint64x1_t LKJI____ = vcreate_u64(L | (K << 8) | (J << 16) | (I << 24));
+ const uint64x1_t LKJI____ =
+ vcreate_u64((uint64_t)L | (K << 8) | (J << 16) | (I << 24));
const uint64x1_t LKJIXABC = vorr_u64(LKJI____, ____XABC);
const uint8x8_t KJIXABC_ = vreinterpret_u8_u64(vshr_n_u64(LKJIXABC, 8));
const uint8x8_t JIXABC__ = vreinterpret_u8_u64(vshr_n_u64(LKJIXABC, 16));
@@ -1427,10 +1428,16 @@ static WEBP_INLINE void DC8_NEON(uint8_t* dst, int do_top, int do_left) {
if (do_top) {
const uint8x8_t A = vld1_u8(dst - BPS); // top row
+#if defined(__aarch64__)
+ const uint16x8_t B = vmovl_u8(A);
+ const uint16_t p2 = vaddvq_u16(B);
+ sum_top = vdupq_n_u16(p2);
+#else
const uint16x4_t p0 = vpaddl_u8(A); // cascading summation of the top
const uint16x4_t p1 = vpadd_u16(p0, p0);
const uint16x4_t p2 = vpadd_u16(p1, p1);
sum_top = vcombine_u16(p2, p2);
+#endif
}
if (do_left) {
diff --git a/thirdparty/libwebp/src/dsp/dsp.h b/thirdparty/libwebp/src/dsp/dsp.h
index fafc2d05d3..a784de334a 100644
--- a/thirdparty/libwebp/src/dsp/dsp.h
+++ b/thirdparty/libwebp/src/dsp/dsp.h
@@ -246,9 +246,9 @@ extern VP8Fdct VP8FTransform2; // performs two transforms at a time
extern VP8WHT VP8FTransformWHT;
// Predictions
// *dst is the destination block. *top and *left can be NULL.
-typedef void (*VP8IntraPreds)(uint8_t *dst, const uint8_t* left,
+typedef void (*VP8IntraPreds)(uint8_t* dst, const uint8_t* left,
const uint8_t* top);
-typedef void (*VP8Intra4Preds)(uint8_t *dst, const uint8_t* top);
+typedef void (*VP8Intra4Preds)(uint8_t* dst, const uint8_t* top);
extern VP8Intra4Preds VP8EncPredLuma4;
extern VP8IntraPreds VP8EncPredLuma16;
extern VP8IntraPreds VP8EncPredChroma8;
diff --git a/thirdparty/libwebp/src/dsp/lossless.c b/thirdparty/libwebp/src/dsp/lossless.c
index d05af84e7b..aad5f43ec9 100644
--- a/thirdparty/libwebp/src/dsp/lossless.c
+++ b/thirdparty/libwebp/src/dsp/lossless.c
@@ -81,7 +81,7 @@ static WEBP_INLINE uint32_t ClampedAddSubtractHalf(uint32_t c0, uint32_t c1,
// gcc <= 4.9 on ARM generates incorrect code in Select() when Sub3() is
// inlined.
-#if defined(__arm__) && LOCAL_GCC_VERSION <= 0x409
+#if defined(__arm__) && defined(__GNUC__) && LOCAL_GCC_VERSION <= 0x409
# define LOCAL_INLINE __attribute__ ((noinline))
#else
# define LOCAL_INLINE WEBP_INLINE
@@ -167,15 +167,20 @@ static uint32_t Predictor13_C(uint32_t left, const uint32_t* const top) {
return pred;
}
-GENERATE_PREDICTOR_ADD(Predictor0_C, PredictorAdd0_C)
+static void PredictorAdd0_C(const uint32_t* in, const uint32_t* upper,
+ int num_pixels, uint32_t* out) {
+ int x;
+ (void)upper;
+ for (x = 0; x < num_pixels; ++x) out[x] = VP8LAddPixels(in[x], ARGB_BLACK);
+}
static void PredictorAdd1_C(const uint32_t* in, const uint32_t* upper,
int num_pixels, uint32_t* out) {
int i;
uint32_t left = out[-1];
+ (void)upper;
for (i = 0; i < num_pixels; ++i) {
out[i] = left = VP8LAddPixels(in[i], left);
}
- (void)upper;
}
GENERATE_PREDICTOR_ADD(Predictor2_C, PredictorAdd2_C)
GENERATE_PREDICTOR_ADD(Predictor3_C, PredictorAdd3_C)
diff --git a/thirdparty/libwebp/src/dsp/lossless_common.h b/thirdparty/libwebp/src/dsp/lossless_common.h
index a2648d1737..9c2ebe6809 100644
--- a/thirdparty/libwebp/src/dsp/lossless_common.h
+++ b/thirdparty/libwebp/src/dsp/lossless_common.h
@@ -177,6 +177,7 @@ uint32_t VP8LSubPixels(uint32_t a, uint32_t b) {
static void PREDICTOR_ADD(const uint32_t* in, const uint32_t* upper, \
int num_pixels, uint32_t* out) { \
int x; \
+ assert(upper != NULL); \
for (x = 0; x < num_pixels; ++x) { \
const uint32_t pred = (PREDICTOR)(out[x - 1], upper + x); \
out[x] = VP8LAddPixels(in[x], pred); \
@@ -189,6 +190,7 @@ static void PREDICTOR_ADD(const uint32_t* in, const uint32_t* upper, \
static void PREDICTOR_SUB(const uint32_t* in, const uint32_t* upper, \
int num_pixels, uint32_t* out) { \
int x; \
+ assert(upper != NULL); \
for (x = 0; x < num_pixels; ++x) { \
const uint32_t pred = (PREDICTOR)(in[x - 1], upper + x); \
out[x] = VP8LSubPixels(in[x], pred); \
diff --git a/thirdparty/libwebp/src/dsp/lossless_enc_sse2.c b/thirdparty/libwebp/src/dsp/lossless_enc_sse2.c
index 8adc52139b..e676f6fdc9 100644
--- a/thirdparty/libwebp/src/dsp/lossless_enc_sse2.c
+++ b/thirdparty/libwebp/src/dsp/lossless_enc_sse2.c
@@ -455,8 +455,9 @@ static void PredictorSub0_SSE2(const uint32_t* in, const uint32_t* upper,
_mm_storeu_si128((__m128i*)&out[i], res);
}
if (i != num_pixels) {
- VP8LPredictorsSub_C[0](in + i, upper + i, num_pixels - i, out + i);
+ VP8LPredictorsSub_C[0](in + i, NULL, num_pixels - i, out + i);
}
+ (void)upper;
}
#define GENERATE_PREDICTOR_1(X, IN) \
diff --git a/thirdparty/libwebp/src/dsp/lossless_sse2.c b/thirdparty/libwebp/src/dsp/lossless_sse2.c
index 17d7576419..aef0cee1b3 100644
--- a/thirdparty/libwebp/src/dsp/lossless_sse2.c
+++ b/thirdparty/libwebp/src/dsp/lossless_sse2.c
@@ -191,8 +191,9 @@ static void PredictorAdd0_SSE2(const uint32_t* in, const uint32_t* upper,
_mm_storeu_si128((__m128i*)&out[i], res);
}
if (i != num_pixels) {
- VP8LPredictorsAdd_C[0](in + i, upper + i, num_pixels - i, out + i);
+ VP8LPredictorsAdd_C[0](in + i, NULL, num_pixels - i, out + i);
}
+ (void)upper;
}
// Predictor1: left.
diff --git a/thirdparty/libwebp/src/dsp/upsampling_msa.c b/thirdparty/libwebp/src/dsp/upsampling_msa.c
index 99eea70e7d..f2e03e85e9 100644
--- a/thirdparty/libwebp/src/dsp/upsampling_msa.c
+++ b/thirdparty/libwebp/src/dsp/upsampling_msa.c
@@ -576,9 +576,9 @@ static void FUNC_NAME(const uint8_t* top_y, const uint8_t* bot_y, \
const uint32_t l_uv = ((cur_u[0]) | ((cur_v[0]) << 16)); \
const uint32_t uv0 = (3 * tl_uv + l_uv + 0x00020002u) >> 2; \
const uint8_t* ptop_y = &top_y[1]; \
- uint8_t *ptop_dst = top_dst + XSTEP; \
+ uint8_t* ptop_dst = top_dst + XSTEP; \
const uint8_t* pbot_y = &bot_y[1]; \
- uint8_t *pbot_dst = bot_dst + XSTEP; \
+ uint8_t* pbot_dst = bot_dst + XSTEP; \
\
FUNC(top_y[0], uv0 & 0xff, (uv0 >> 16), top_dst); \
if (bot_y != NULL) { \
diff --git a/thirdparty/libwebp/src/dsp/upsampling_neon.c b/thirdparty/libwebp/src/dsp/upsampling_neon.c
index 17cbc9f911..6ba71a7de5 100644
--- a/thirdparty/libwebp/src/dsp/upsampling_neon.c
+++ b/thirdparty/libwebp/src/dsp/upsampling_neon.c
@@ -58,8 +58,8 @@
} while (0)
// Turn the macro into a function for reducing code-size when non-critical
-static void Upsample16Pixels_NEON(const uint8_t *r1, const uint8_t *r2,
- uint8_t *out) {
+static void Upsample16Pixels_NEON(const uint8_t* r1, const uint8_t* r2,
+ uint8_t* out) {
UPSAMPLE_16PIXELS(r1, r2, out);
}
@@ -190,14 +190,14 @@ static const int16_t kCoeffs1[4] = { 19077, 26149, 6419, 13320 };
}
#define NEON_UPSAMPLE_FUNC(FUNC_NAME, FMT, XSTEP) \
-static void FUNC_NAME(const uint8_t *top_y, const uint8_t *bottom_y, \
- const uint8_t *top_u, const uint8_t *top_v, \
- const uint8_t *cur_u, const uint8_t *cur_v, \
- uint8_t *top_dst, uint8_t *bottom_dst, int len) { \
+static void FUNC_NAME(const uint8_t* top_y, const uint8_t* bottom_y, \
+ const uint8_t* top_u, const uint8_t* top_v, \
+ const uint8_t* cur_u, const uint8_t* cur_v, \
+ uint8_t* top_dst, uint8_t* bottom_dst, int len) { \
int block; \
/* 16 byte aligned array to cache reconstructed u and v */ \
uint8_t uv_buf[2 * 32 + 15]; \
- uint8_t *const r_uv = (uint8_t*)((uintptr_t)(uv_buf + 15) & ~15); \
+ uint8_t* const r_uv = (uint8_t*)((uintptr_t)(uv_buf + 15) & ~15); \
const int uv_len = (len + 1) >> 1; \
/* 9 pixels must be read-able for each block */ \
const int num_blocks = (uv_len - 1) >> 3; \
diff --git a/thirdparty/libwebp/src/enc/histogram_enc.c b/thirdparty/libwebp/src/enc/histogram_enc.c
index d89b98524a..a4e6bf3a98 100644
--- a/thirdparty/libwebp/src/enc/histogram_enc.c
+++ b/thirdparty/libwebp/src/enc/histogram_enc.c
@@ -641,7 +641,7 @@ static void HistogramAnalyzeEntropyBin(VP8LHistogramSet* const image_histo,
// Merges some histograms with same bin_id together if it's advantageous.
// Sets the remaining histograms to NULL.
static void HistogramCombineEntropyBin(VP8LHistogramSet* const image_histo,
- int *num_used,
+ int* num_used,
const uint16_t* const clusters,
uint16_t* const cluster_mappings,
VP8LHistogram* cur_combo,
diff --git a/thirdparty/libwebp/src/enc/picture_csp_enc.c b/thirdparty/libwebp/src/enc/picture_csp_enc.c
index 02d9df76d5..718e014ed2 100644
--- a/thirdparty/libwebp/src/enc/picture_csp_enc.c
+++ b/thirdparty/libwebp/src/enc/picture_csp_enc.c
@@ -29,11 +29,15 @@
#define USE_INVERSE_ALPHA_TABLE
#ifdef WORDS_BIGENDIAN
-#define ALPHA_OFFSET 0 // uint32_t 0xff000000 is 0xff,00,00,00 in memory
+// uint32_t 0xff000000 is 0xff,00,00,00 in memory
+#define CHANNEL_OFFSET(i) (i)
#else
-#define ALPHA_OFFSET 3 // uint32_t 0xff000000 is 0x00,00,00,ff in memory
+// uint32_t 0xff000000 is 0x00,00,00,ff in memory
+#define CHANNEL_OFFSET(i) (3-(i))
#endif
+#define ALPHA_OFFSET CHANNEL_OFFSET(0)
+
//------------------------------------------------------------------------------
// Detection of non-trivial transparency
@@ -997,10 +1001,10 @@ static int PictureARGBToYUVA(WebPPicture* picture, WebPEncCSP colorspace,
return WebPEncodingSetError(picture, VP8_ENC_ERROR_INVALID_CONFIGURATION);
} else {
const uint8_t* const argb = (const uint8_t*)picture->argb;
- const uint8_t* const a = argb + (0 ^ ALPHA_OFFSET);
- const uint8_t* const r = argb + (1 ^ ALPHA_OFFSET);
- const uint8_t* const g = argb + (2 ^ ALPHA_OFFSET);
- const uint8_t* const b = argb + (3 ^ ALPHA_OFFSET);
+ const uint8_t* const a = argb + CHANNEL_OFFSET(0);
+ const uint8_t* const r = argb + CHANNEL_OFFSET(1);
+ const uint8_t* const g = argb + CHANNEL_OFFSET(2);
+ const uint8_t* const b = argb + CHANNEL_OFFSET(3);
picture->colorspace = WEBP_YUV420;
return ImportYUVAFromRGBA(r, g, b, a, 4, 4 * picture->argb_stride,
@@ -1050,7 +1054,7 @@ int WebPPictureYUVAToARGB(WebPPicture* picture) {
const int height = picture->height;
const int argb_stride = 4 * picture->argb_stride;
uint8_t* dst = (uint8_t*)picture->argb;
- const uint8_t *cur_u = picture->u, *cur_v = picture->v, *cur_y = picture->y;
+ const uint8_t* cur_u = picture->u, *cur_v = picture->v, *cur_y = picture->y;
WebPUpsampleLinePairFunc upsample =
WebPGetLinePairConverter(ALPHA_OFFSET > 0);
diff --git a/thirdparty/libwebp/src/enc/vp8i_enc.h b/thirdparty/libwebp/src/enc/vp8i_enc.h
index 24e1944610..fedcaeea27 100644
--- a/thirdparty/libwebp/src/enc/vp8i_enc.h
+++ b/thirdparty/libwebp/src/enc/vp8i_enc.h
@@ -31,8 +31,8 @@ extern "C" {
// version numbers
#define ENC_MAJ_VERSION 1
-#define ENC_MIN_VERSION 0
-#define ENC_REV_VERSION 3
+#define ENC_MIN_VERSION 1
+#define ENC_REV_VERSION 0
enum { MAX_LF_LEVELS = 64, // Maximum loop filter level
MAX_VARIABLE_LEVEL = 67, // last (inclusive) level with variable cost
@@ -249,7 +249,7 @@ typedef struct {
int percent0_; // saved initial progress percent
DError left_derr_; // left error diffusion (u/v)
- DError *top_derr_; // top diffusion error - NULL if disabled
+ DError* top_derr_; // top diffusion error - NULL if disabled
uint8_t* y_left_; // left luma samples (addressable from index -1 to 15).
uint8_t* u_left_; // left u samples (addressable from index -1 to 7)
diff --git a/thirdparty/libwebp/src/mux/muxi.h b/thirdparty/libwebp/src/mux/muxi.h
index 7bc0b07e9b..ad3e1bdb97 100644
--- a/thirdparty/libwebp/src/mux/muxi.h
+++ b/thirdparty/libwebp/src/mux/muxi.h
@@ -28,8 +28,8 @@ extern "C" {
// Defines and constants.
#define MUX_MAJ_VERSION 1
-#define MUX_MIN_VERSION 0
-#define MUX_REV_VERSION 3
+#define MUX_MIN_VERSION 1
+#define MUX_REV_VERSION 0
// Chunk object.
typedef struct WebPChunk WebPChunk;
diff --git a/thirdparty/libwebp/src/mux/muxread.c b/thirdparty/libwebp/src/mux/muxread.c
index 268f6acb53..ae3b876bc5 100644
--- a/thirdparty/libwebp/src/mux/muxread.c
+++ b/thirdparty/libwebp/src/mux/muxread.c
@@ -100,7 +100,7 @@ static int MuxImageParse(const WebPChunk* const chunk, int copy_data,
WebPMuxImage* const wpi) {
const uint8_t* bytes = chunk->data_.bytes;
size_t size = chunk->data_.size;
- const uint8_t* const last = bytes + size;
+ const uint8_t* const last = (bytes == NULL) ? NULL : bytes + size;
WebPChunk subchunk;
size_t subchunk_size;
WebPChunk** unknown_chunk_list = &wpi->unknown_;
diff --git a/thirdparty/libwebp/src/utils/color_cache_utils.h b/thirdparty/libwebp/src/utils/color_cache_utils.h
index ec21d5199b..b45d47c2d5 100644
--- a/thirdparty/libwebp/src/utils/color_cache_utils.h
+++ b/thirdparty/libwebp/src/utils/color_cache_utils.h
@@ -26,7 +26,7 @@ extern "C" {
// Main color cache struct.
typedef struct {
- uint32_t *colors_; // color entries
+ uint32_t* colors_; // color entries
int hash_shift_; // Hash shift: 32 - hash_bits_.
int hash_bits_;
} VP8LColorCache;
diff --git a/thirdparty/libwebp/src/utils/thread_utils.c b/thirdparty/libwebp/src/utils/thread_utils.c
index 438296b45f..4e470e17ac 100644
--- a/thirdparty/libwebp/src/utils/thread_utils.c
+++ b/thirdparty/libwebp/src/utils/thread_utils.c
@@ -73,7 +73,7 @@ typedef struct {
#endif
static int pthread_create(pthread_t* const thread, const void* attr,
- unsigned int (__stdcall *start)(void*), void* arg) {
+ unsigned int (__stdcall* start)(void*), void* arg) {
(void)attr;
#ifdef USE_CREATE_THREAD
*thread = CreateThread(NULL, /* lpThreadAttributes */
diff --git a/thirdparty/libwebp/src/utils/utils.c b/thirdparty/libwebp/src/utils/utils.c
index 44d5c14f01..764f752b82 100644
--- a/thirdparty/libwebp/src/utils/utils.c
+++ b/thirdparty/libwebp/src/utils/utils.c
@@ -216,9 +216,14 @@ void WebPSafeFree(void* const ptr) {
free(ptr);
}
-// Public API function.
+// Public API functions.
+
+void* WebPMalloc(size_t size) {
+ return WebPSafeMalloc(1, size);
+}
+
void WebPFree(void* ptr) {
- free(ptr);
+ WebPSafeFree(ptr);
}
//------------------------------------------------------------------------------
diff --git a/thirdparty/libwebp/src/webp/decode.h b/thirdparty/libwebp/src/webp/decode.h
index ae8bfe840e..80dd0ef0cc 100644
--- a/thirdparty/libwebp/src/webp/decode.h
+++ b/thirdparty/libwebp/src/webp/decode.h
@@ -20,7 +20,7 @@
extern "C" {
#endif
-#define WEBP_DECODER_ABI_VERSION 0x0208 // MAJOR(8b) + MINOR(8b)
+#define WEBP_DECODER_ABI_VERSION 0x0209 // MAJOR(8b) + MINOR(8b)
// Note: forward declaring enumerations is not allowed in (strict) C and C++,
// the types are left here for reference.
@@ -91,9 +91,6 @@ WEBP_EXTERN uint8_t* WebPDecodeYUV(const uint8_t* data, size_t data_size,
uint8_t** u, uint8_t** v,
int* stride, int* uv_stride);
-// Releases memory returned by the WebPDecode*() functions above.
-WEBP_EXTERN void WebPFree(void* ptr);
-
// These five functions are variants of the above ones, that decode the image
// directly into a pre-allocated buffer 'output_buffer'. The maximum storage
// available in this buffer is indicated by 'output_buffer_size'. If this
diff --git a/thirdparty/libwebp/src/webp/encode.h b/thirdparty/libwebp/src/webp/encode.h
index 339f8810aa..655166e7d4 100644
--- a/thirdparty/libwebp/src/webp/encode.h
+++ b/thirdparty/libwebp/src/webp/encode.h
@@ -20,7 +20,7 @@
extern "C" {
#endif
-#define WEBP_ENCODER_ABI_VERSION 0x020e // MAJOR(8b) + MINOR(8b)
+#define WEBP_ENCODER_ABI_VERSION 0x020f // MAJOR(8b) + MINOR(8b)
// Note: forward declaring enumerations is not allowed in (strict) C and C++,
// the types are left here for reference.
@@ -79,9 +79,6 @@ WEBP_EXTERN size_t WebPEncodeLosslessBGRA(const uint8_t* bgra,
int width, int height, int stride,
uint8_t** output);
-// Releases memory returned by the WebPEncode*() functions above.
-WEBP_EXTERN void WebPFree(void* ptr);
-
//------------------------------------------------------------------------------
// Coding parameters
@@ -306,7 +303,7 @@ struct WebPPicture {
// YUV input (mostly used for input to lossy compression)
WebPEncCSP colorspace; // colorspace: should be YUV420 for now (=Y'CbCr).
int width, height; // dimensions (less or equal to WEBP_MAX_DIMENSION)
- uint8_t *y, *u, *v; // pointers to luma/chroma planes.
+ uint8_t* y, *u, *v; // pointers to luma/chroma planes.
int y_stride, uv_stride; // luma/chroma strides.
uint8_t* a; // pointer to the alpha plane
int a_stride; // stride of the alpha plane
@@ -350,7 +347,7 @@ struct WebPPicture {
uint32_t pad3[3]; // padding for later use
// Unused for now
- uint8_t *pad4, *pad5;
+ uint8_t* pad4, *pad5;
uint32_t pad6[8]; // padding for later use
// PRIVATE FIELDS
diff --git a/thirdparty/libwebp/src/webp/mux.h b/thirdparty/libwebp/src/webp/mux.h
index 66096a92e0..7d27489a40 100644
--- a/thirdparty/libwebp/src/webp/mux.h
+++ b/thirdparty/libwebp/src/webp/mux.h
@@ -57,7 +57,7 @@ extern "C" {
WebPMuxGetChunk(mux, "ICCP", &icc_profile);
// ... (Consume icc_data).
WebPMuxDelete(mux);
- free(data);
+ WebPFree(data);
*/
// Note: forward declaring enumerations is not allowed in (strict) C and C++,
@@ -245,7 +245,7 @@ WEBP_EXTERN WebPMuxError WebPMuxPushFrame(
WebPMux* mux, const WebPMuxFrameInfo* frame, int copy_data);
// Gets the nth frame from the mux object.
-// The content of 'frame->bitstream' is allocated using malloc(), and NOT
+// The content of 'frame->bitstream' is allocated using WebPMalloc(), and NOT
// owned by the 'mux' object. It MUST be deallocated by the caller by calling
// WebPDataClear().
// nth=0 has a special meaning - last position.
@@ -376,10 +376,10 @@ WEBP_EXTERN WebPMuxError WebPMuxNumChunks(const WebPMux* mux,
// Assembles all chunks in WebP RIFF format and returns in 'assembled_data'.
// This function also validates the mux object.
// Note: The content of 'assembled_data' will be ignored and overwritten.
-// Also, the content of 'assembled_data' is allocated using malloc(), and NOT
-// owned by the 'mux' object. It MUST be deallocated by the caller by calling
-// WebPDataClear(). It's always safe to call WebPDataClear() upon return,
-// even in case of error.
+// Also, the content of 'assembled_data' is allocated using WebPMalloc(), and
+// NOT owned by the 'mux' object. It MUST be deallocated by the caller by
+// calling WebPDataClear(). It's always safe to call WebPDataClear() upon
+// return, even in case of error.
// Parameters:
// mux - (in/out) object whose chunks are to be assembled
// assembled_data - (out) assembled WebP data
diff --git a/thirdparty/libwebp/src/webp/mux_types.h b/thirdparty/libwebp/src/webp/mux_types.h
index ceea77dfc6..2fe8195839 100644
--- a/thirdparty/libwebp/src/webp/mux_types.h
+++ b/thirdparty/libwebp/src/webp/mux_types.h
@@ -14,7 +14,6 @@
#ifndef WEBP_WEBP_MUX_TYPES_H_
#define WEBP_WEBP_MUX_TYPES_H_
-#include <stdlib.h> // free()
#include <string.h> // memset()
#include "./types.h"
@@ -56,6 +55,7 @@ typedef enum WebPMuxAnimBlend {
// Data type used to describe 'raw' data, e.g., chunk data
// (ICC profile, metadata) and WebP compressed image data.
+// 'bytes' memory must be allocated using WebPMalloc() and such.
struct WebPData {
const uint8_t* bytes;
size_t size;
@@ -68,11 +68,11 @@ static WEBP_INLINE void WebPDataInit(WebPData* webp_data) {
}
}
-// Clears the contents of the 'webp_data' object by calling free(). Does not
-// deallocate the object itself.
+// Clears the contents of the 'webp_data' object by calling WebPFree().
+// Does not deallocate the object itself.
static WEBP_INLINE void WebPDataClear(WebPData* webp_data) {
if (webp_data != NULL) {
- free((void*)webp_data->bytes);
+ WebPFree((void*)webp_data->bytes);
WebPDataInit(webp_data);
}
}
@@ -83,7 +83,7 @@ static WEBP_INLINE int WebPDataCopy(const WebPData* src, WebPData* dst) {
if (src == NULL || dst == NULL) return 0;
WebPDataInit(dst);
if (src->bytes != NULL && src->size != 0) {
- dst->bytes = (uint8_t*)malloc(src->size);
+ dst->bytes = (uint8_t*)WebPMalloc(src->size);
if (dst->bytes == NULL) return 0;
memcpy((void*)dst->bytes, src->bytes, src->size);
dst->size = src->size;
diff --git a/thirdparty/libwebp/src/webp/types.h b/thirdparty/libwebp/src/webp/types.h
index 0ce2622e41..47f7f2b007 100644
--- a/thirdparty/libwebp/src/webp/types.h
+++ b/thirdparty/libwebp/src/webp/types.h
@@ -7,7 +7,7 @@
// be found in the AUTHORS file in the root of the source tree.
// -----------------------------------------------------------------------------
//
-// Common types
+// Common types + memory wrappers
//
// Author: Skal (pascal.massimino@gmail.com)
@@ -49,4 +49,20 @@ typedef long long int int64_t;
// Macro to check ABI compatibility (same major revision number)
#define WEBP_ABI_IS_INCOMPATIBLE(a, b) (((a) >> 8) != ((b) >> 8))
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// Allocates 'size' bytes of memory. Returns NULL upon error. Memory
+// must be deallocated by calling WebPFree(). This function is made available
+// by the core 'libwebp' library.
+WEBP_EXTERN void* WebPMalloc(size_t size);
+
+// Releases memory returned by the WebPDecode*() functions (from decode.h).
+WEBP_EXTERN void WebPFree(void* ptr);
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
#endif // WEBP_WEBP_TYPES_H_
diff --git a/thirdparty/xatlas/LICENSE b/thirdparty/xatlas/LICENSE
index 94d0c60485..9e61e15fb7 100644
--- a/thirdparty/xatlas/LICENSE
+++ b/thirdparty/xatlas/LICENSE
@@ -1,14 +1,21 @@
-xatlas
-https://github.com/jpcy/xatlas
-Copyright (c) 2018 Jonathan Young
+MIT License
-thekla_atlas
-https://github.com/Thekla/thekla_atlas
-Copyright (c) 2013 Thekla, Inc
-Copyright NVIDIA Corporation 2006 -- Ignacio Castano <icastano@nvidia.com>
+Copyright (c) 2018-2019 Jonathan Young
-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:
+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 above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+THE 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. \ No newline at end of file
diff --git a/thirdparty/xatlas/xatlas.cpp b/thirdparty/xatlas/xatlas.cpp
index 56794211a6..80cacf9746 100644
--- a/thirdparty/xatlas/xatlas.cpp
+++ b/thirdparty/xatlas/xatlas.cpp
@@ -33,7 +33,6 @@ https://github.com/brandonpelfrey/Fast-BVH
MIT License
Copyright (c) 2012 Brandon Pelfrey
*/
-#include <algorithm>
#include <atomic>
#include <condition_variable>
#include <mutex>
@@ -114,22 +113,25 @@ Copyright (c) 2012 Brandon Pelfrey
#define XA_UNUSED(a) ((void)(a))
-#define XA_GROW_CHARTS_COPLANAR 1
#define XA_MERGE_CHARTS 1
#define XA_MERGE_CHARTS_MIN_NORMAL_DEVIATION 0.5f
#define XA_RECOMPUTE_CHARTS 1
-#define XA_SKIP_PARAMETERIZATION 0 // Use the orthogonal parameterization from segment::Atlas
#define XA_CLOSE_HOLES_CHECK_EDGE_INTERSECTION 0
+#define XA_FIX_INTERNAL_BOUNDARY_LOOPS 1
+#define XA_PRINT_CHART_WARNINGS 0
#define XA_DEBUG_HEAP 0
#define XA_DEBUG_SINGLE_CHART 0
#define XA_DEBUG_EXPORT_ATLAS_IMAGES 0
+#define XA_DEBUG_EXPORT_ATLAS_IMAGES_PER_CHART 0 // Export an atlas image after each chart is added.
+#define XA_DEBUG_EXPORT_BOUNDARY_GRID 0
+#define XA_DEBUG_EXPORT_TGA (XA_DEBUG_EXPORT_ATLAS_IMAGES || XA_DEBUG_EXPORT_BOUNDARY_GRID)
#define XA_DEBUG_EXPORT_OBJ_SOURCE_MESHES 0
#define XA_DEBUG_EXPORT_OBJ_CHART_GROUPS 0
+#define XA_DEBUG_EXPORT_OBJ_PLANAR_REGIONS 0
#define XA_DEBUG_EXPORT_OBJ_CHARTS 0
#define XA_DEBUG_EXPORT_OBJ_BEFORE_FIX_TJUNCTION 0
#define XA_DEBUG_EXPORT_OBJ_CLOSE_HOLES_ERROR 0
-#define XA_DEBUG_EXPORT_OBJ_NOT_DISK 0
#define XA_DEBUG_EXPORT_OBJ_CHARTS_AFTER_PARAMETERIZATION 0
#define XA_DEBUG_EXPORT_OBJ_INVALID_PARAMETERIZATION 0
#define XA_DEBUG_EXPORT_OBJ_RECOMPUTED_CHARTS 0
@@ -137,10 +139,10 @@ Copyright (c) 2012 Brandon Pelfrey
#define XA_DEBUG_EXPORT_OBJ (0 \
|| XA_DEBUG_EXPORT_OBJ_SOURCE_MESHES \
|| XA_DEBUG_EXPORT_OBJ_CHART_GROUPS \
+ || XA_DEBUG_EXPORT_OBJ_PLANAR_REGIONS \
|| XA_DEBUG_EXPORT_OBJ_CHARTS \
|| XA_DEBUG_EXPORT_OBJ_BEFORE_FIX_TJUNCTION \
|| XA_DEBUG_EXPORT_OBJ_CLOSE_HOLES_ERROR \
- || XA_DEBUG_EXPORT_OBJ_NOT_DISK \
|| XA_DEBUG_EXPORT_OBJ_CHARTS_AFTER_PARAMETERIZATION \
|| XA_DEBUG_EXPORT_OBJ_INVALID_PARAMETERIZATION \
|| XA_DEBUG_EXPORT_OBJ_RECOMPUTED_CHARTS)
@@ -166,6 +168,10 @@ struct MemTag
enum
{
Default,
+ BitImage,
+ BVH,
+ FullVector,
+ Matrix,
Mesh,
MeshBoundaries,
MeshColocals,
@@ -174,6 +180,10 @@ struct MemTag
MeshNormals,
MeshPositions,
MeshTexcoords,
+ SegmentAtlasChartCandidates,
+ SegmentAtlasChartFaces,
+ SegmentAtlasMeshData,
+ SegmentAtlasPlanarRegions,
Count
};
};
@@ -192,7 +202,7 @@ struct AllocHeader
static std::mutex s_allocMutex;
static AllocHeader *s_allocRoot = nullptr;
-static size_t s_allocTotalSize = 0, s_allocPeakSize = 0, s_allocTotalTagSize[MemTag::Count] = { 0 }, s_allocPeakTagSize[MemTag::Count] = { 0 };
+static size_t s_allocTotalCount = 0, s_allocTotalSize = 0, s_allocPeakSize = 0, s_allocCount[MemTag::Count] = { 0 }, s_allocTotalTagSize[MemTag::Count] = { 0 }, s_allocPeakTagSize[MemTag::Count] = { 0 };
static uint32_t s_allocId =0 ;
static constexpr uint32_t kAllocRedzone = 0x12345678;
@@ -245,9 +255,11 @@ static void *Realloc(void *ptr, size_t size, int tag, const char *file, int line
s_allocRoot = header;
header->next->prev = header;
}
+ s_allocTotalCount++;
s_allocTotalSize += size;
if (s_allocTotalSize > s_allocPeakSize)
s_allocPeakSize = s_allocTotalSize;
+ s_allocCount[tag]++;
s_allocTotalTagSize[tag] += size;
if (s_allocTotalTagSize[tag] > s_allocPeakTagSize[tag])
s_allocPeakTagSize[tag] = s_allocTotalTagSize[tag];
@@ -287,9 +299,14 @@ static void ReportLeaks()
static void PrintMemoryUsage()
{
+ XA_PRINT("Total allocations: %zu\n", s_allocTotalCount);
XA_PRINT("Memory usage: %0.2fMB current, %0.2fMB peak\n", internal::s_allocTotalSize / 1024.0f / 1024.0f, internal::s_allocPeakSize / 1024.0f / 1024.0f);
static const char *labels[] = { // Sync with MemTag
"Default",
+ "BitImage",
+ "BVH",
+ "FullVector",
+ "Matrix",
"Mesh",
"MeshBoundaries",
"MeshColocals",
@@ -297,10 +314,14 @@ static void PrintMemoryUsage()
"MeshIndices",
"MeshNormals",
"MeshPositions",
- "MeshTexcoords"
+ "MeshTexcoords",
+ "SegmentAtlasChartCandidates",
+ "SegmentAtlasChartFaces",
+ "SegmentAtlasMeshData",
+ "SegmentAtlasPlanarRegions"
};
for (int i = 0; i < MemTag::Count; i++) {
- XA_PRINT(" %s: %0.2fMB current, %0.2fMB peak\n", labels[i], internal::s_allocTotalTagSize[i] / 1024.0f / 1024.0f, internal::s_allocPeakTagSize[i] / 1024.0f / 1024.0f);
+ XA_PRINT(" %s: %zu allocations, %0.2fMB current, %0.2fMB peak\n", labels[i], internal::s_allocCount[i], internal::s_allocTotalTagSize[i] / 1024.0f / 1024.0f, internal::s_allocPeakTagSize[i] / 1024.0f / 1024.0f);
}
}
@@ -308,7 +329,9 @@ static void PrintMemoryUsage()
#else
static void *Realloc(void *ptr, size_t size, int /*tag*/, const char * /*file*/, int /*line*/)
{
- if (ptr && size == 0 && s_free) {
+ if (size == 0 && !ptr)
+ return nullptr;
+ if (size == 0 && s_free) {
s_free(ptr);
return nullptr;
}
@@ -333,7 +356,6 @@ struct ProfileData
std::atomic<clock_t> addMeshThread;
std::atomic<clock_t> addMeshCreateColocals;
std::atomic<clock_t> addMeshCreateFaceGroups;
- std::atomic<clock_t> addMeshCreateBoundaries;
std::atomic<clock_t> addMeshCreateChartGroupsReal;
std::atomic<clock_t> addMeshCreateChartGroupsThread;
clock_t computeChartsReal;
@@ -362,7 +384,6 @@ struct ProfileData
clock_t packChartsRasterize;
clock_t packChartsDilate;
clock_t packChartsFindLocation;
- std::atomic<clock_t> packChartsFindLocationThread;
clock_t packChartsBlit;
clock_t buildOutputMeshes;
};
@@ -386,6 +407,7 @@ static double clockToSeconds(clock_t c)
static constexpr float kPi = 3.14159265358979323846f;
static constexpr float kPi2 = 6.28318530717958647692f;
+static constexpr float kPi4 = 12.56637061435917295384f;
static constexpr float kEpsilon = 0.0001f;
static constexpr float kAreaEpsilon = FLT_EPSILON;
static constexpr float kNormalEpsilon = 0.001f;
@@ -430,11 +452,9 @@ static T clamp(const T &x, const T &a, const T &b)
template <typename T>
static void swap(T &a, T &b)
{
- T temp;
- temp = a;
+ T temp = a;
a = b;
b = temp;
- temp = T();
}
union FloatUint32
@@ -620,6 +640,14 @@ static Vector2 normalize(const Vector2 &v, float epsilon)
return n;
}
+static Vector2 normalizeSafe(const Vector2 &v, const Vector2 &fallback, float epsilon)
+{
+ float l = length(v);
+ if (isZero(l, epsilon))
+ return fallback;
+ return v * (1.0f / l);
+}
+
static bool equal(const Vector2 &v1, const Vector2 &v2, float epsilon)
{
return equal(v1.x, v2.x, epsilon) && equal(v1.y, v2.y, epsilon);
@@ -640,23 +668,19 @@ static bool isFinite(const Vector2 &v)
return isFinite(v.x) && isFinite(v.y);
}
-// Note, this is the area scaled by 2!
-static float triangleArea(const Vector2 &v0, const Vector2 &v1)
-{
- return (v0.x * v1.y - v0.y * v1.x); // * 0.5f;
-}
-
static float triangleArea(const Vector2 &a, const Vector2 &b, const Vector2 &c)
{
// IC: While it may be appealing to use the following expression:
- //return (c.x * a.y + a.x * b.y + b.x * c.y - b.x * a.y - c.x * b.y - a.x * c.y); // * 0.5f;
+ //return (c.x * a.y + a.x * b.y + b.x * c.y - b.x * a.y - c.x * b.y - a.x * c.y) * 0.5f;
// That's actually a terrible idea. Small triangles far from the origin can end up producing fairly large floating point
// numbers and the results becomes very unstable and dependent on the order of the factors.
// Instead, it's preferable to subtract the vertices first, and multiply the resulting small values together. The result
// in this case is always much more accurate (as long as the triangle is small) and less dependent of the location of
// the triangle.
- //return ((a.x - c.x) * (b.y - c.y) - (a.y - c.y) * (b.x - c.x)); // * 0.5f;
- return triangleArea(a - c, b - c);
+ //return ((a.x - c.x) * (b.y - c.y) - (a.y - c.y) * (b.x - c.x)) * 0.5f;
+ const Vector2 v0 = a - c;
+ const Vector2 v1 = b - c;
+ return (v0.x * v1.y - v0.y * v1.x) * 0.5f;
}
static bool linesIntersect(const Vector2 &a1, const Vector2 &a2, const Vector2 &b1, const Vector2 &b2, float epsilon)
@@ -746,11 +770,6 @@ public:
float x, y, z;
};
-static bool operator!=(const Vector3 &a, const Vector3 &b)
-{
- return a.x != b.x || a.y != b.y || a.z != b.z;
-}
-
static Vector3 operator+(const Vector3 &a, const Vector3 &b)
{
return Vector3(a.x + b.x, a.y + b.y, a.z + b.z);
@@ -837,6 +856,33 @@ bool isFinite(const Vector3 &v)
}
#endif
+struct Extents2
+{
+ Vector2 min, max;
+
+ void reset()
+ {
+ min.x = min.y = FLT_MAX;
+ max.x = max.y = -FLT_MAX;
+ }
+
+ void add(Vector2 p)
+ {
+ min = xatlas::internal::min(min, p);
+ max = xatlas::internal::max(max, p);
+ }
+
+ Vector2 midpoint() const
+ {
+ return Vector2(min.x + (max.x - min.x) * 0.5f, min.y + (max.y - min.y) * 0.5f);
+ }
+
+ static bool intersect(Extents2 e1, Extents2 e2)
+ {
+ return e1.min.x <= e2.max.x && e1.max.x >= e2.min.x && e1.min.y <= e2.max.y && e1.max.y >= e2.min.y;
+ }
+};
+
struct Plane
{
Plane() = default;
@@ -979,7 +1025,14 @@ struct AABB
struct ArrayBase
{
- ArrayBase(uint32_t elementSize, int memTag = MemTag::Default) : buffer(nullptr), elementSize(elementSize), size(0), capacity(0), memTag(memTag) {}
+ ArrayBase(uint32_t elementSize, int memTag = MemTag::Default) : buffer(nullptr), elementSize(elementSize), size(0), capacity(0)
+ {
+#if XA_DEBUG_HEAP
+ this->memTag = memTag;
+#else
+ XA_UNUSED(memTag);
+#endif
+ }
~ArrayBase()
{
@@ -991,6 +1044,12 @@ struct ArrayBase
size = 0;
}
+ void copyFrom(const uint8_t *data, uint32_t length)
+ {
+ resize(length, true);
+ memcpy(buffer, data, length * elementSize);
+ }
+
void copyTo(ArrayBase &other) const
{
XA_DEBUG_ASSERT(elementSize == other.elementSize);
@@ -1025,7 +1084,9 @@ struct ArrayBase
other.elementSize = elementSize;
other.size = size;
other.capacity = capacity;
+#if XA_DEBUG_HEAP
other.memTag = memTag;
+#endif
buffer = nullptr;
elementSize = size = capacity = 0;
}
@@ -1043,6 +1104,16 @@ struct ArrayBase
memcpy(&buffer[(size - 1) * elementSize], value, elementSize);
}
+ void push_back(const ArrayBase &other)
+ {
+ XA_DEBUG_ASSERT(elementSize == other.elementSize);
+ if (other.size == 0)
+ return;
+ const uint32_t oldSize = size;
+ resize(size + other.size, false);
+ memcpy(buffer + oldSize * elementSize, other.buffer, other.size * other.elementSize);
+ }
+
// Remove the element at the given index. This is an expensive operation!
void removeAt(uint32_t index)
{
@@ -1083,16 +1154,29 @@ struct ArrayBase
}
} else {
// realloc the buffer
+#if XA_DEBUG_HEAP
buffer = XA_REALLOC_SIZE(memTag, buffer, newCapacity * elementSize);
+#else
+ buffer = XA_REALLOC_SIZE(MemTag::Default, buffer, newCapacity * elementSize);
+#endif
}
capacity = newCapacity;
}
+#if XA_DEBUG_HEAP
+ void setMemTag(int memTag)
+ {
+ this->memTag = memTag;
+ }
+#endif
+
uint8_t *buffer;
uint32_t elementSize;
uint32_t size;
uint32_t capacity;
+#if XA_DEBUG_HEAP
int memTag;
+#endif
};
template<typename T>
@@ -1101,7 +1185,7 @@ class Array
public:
Array(int memTag = MemTag::Default) : m_base(sizeof(T), memTag) {}
Array(const Array&) = delete;
- const Array &operator=(const Array &) = delete;
+ Array &operator=(const Array &) = delete;
XA_INLINE const T &operator[](uint32_t index) const
{
@@ -1123,6 +1207,17 @@ public:
XA_INLINE T *begin() { return (T *)m_base.buffer; }
XA_INLINE void clear() { m_base.clear(); }
+
+ bool contains(const T &value) const
+ {
+ for (uint32_t i = 0; i < m_base.size; i++) {
+ if (((const T *)m_base.buffer)[i] == value)
+ return true;
+ }
+ return false;
+ }
+
+ void copyFrom(const T *data, uint32_t length) { m_base.copyFrom((const uint8_t *)data, length); }
void copyTo(Array &other) const { m_base.copyTo(other.m_base); }
XA_INLINE const T *data() const { return (const T *)m_base.buffer; }
XA_INLINE T *data() { return (T *)m_base.buffer; }
@@ -1131,11 +1226,24 @@ public:
void insertAt(uint32_t index, const T &value) { m_base.insertAt(index, (const uint8_t *)&value); }
void moveTo(Array &other) { m_base.moveTo(other.m_base); }
void push_back(const T &value) { m_base.push_back((const uint8_t *)&value); }
+ void push_back(const Array &other) { m_base.push_back(other.m_base); }
void pop_back() { m_base.pop_back(); }
void removeAt(uint32_t index) { m_base.removeAt(index); }
void reserve(uint32_t desiredSize) { m_base.reserve(desiredSize); }
void resize(uint32_t newSize) { m_base.resize(newSize, true); }
+ void runCtors()
+ {
+ for (uint32_t i = 0; i < m_base.size; i++)
+ new (&((T *)m_base.buffer)[i]) T;
+ }
+
+ void runDtors()
+ {
+ for (uint32_t i = 0; i < m_base.size; i++)
+ ((T *)m_base.buffer)[i].~T();
+ }
+
void setAll(const T &value)
{
auto buffer = (T *)m_base.buffer;
@@ -1143,6 +1251,10 @@ public:
buffer[i] = value;
}
+#if XA_DEBUG_HEAP
+ void setMemTag(int memTag) { m_base.setMemTag(memTag); }
+#endif
+
XA_INLINE uint32_t size() const { return m_base.size; }
XA_INLINE void zeroOutMemory() { memset(m_base.buffer, 0, m_base.elementSize * m_base.size); }
@@ -1150,6 +1262,28 @@ private:
ArrayBase m_base;
};
+template<typename T>
+struct ArrayView
+{
+ ArrayView(Array<T> &a) : data(a.data()), length(a.size()) {}
+ ArrayView(T *data, uint32_t length) : data(data), length(length) {}
+ ArrayView &operator=(Array<T> &a) { data = a.data(); length = a.size(); return *this; }
+ XA_INLINE const T &operator[](uint32_t index) const { XA_DEBUG_ASSERT(index < length); return data[index]; }
+ T *data;
+ uint32_t length;
+};
+
+template<typename T>
+struct ConstArrayView
+{
+ ConstArrayView(const Array<T> &a) : data(a.data()), length(a.size()) {}
+ ConstArrayView(const T *data, uint32_t length) : data(data), length(length) {}
+ ConstArrayView &operator=(const Array<T> &a) { data = a.data(); length = a.size(); return *this; }
+ XA_INLINE const T &operator[](uint32_t index) const { XA_DEBUG_ASSERT(index < length); return data[index]; }
+ const T *data;
+ uint32_t length;
+};
+
/// Basis class to compute tangent space basis, ortogonalizations and to transform vectors from one space to another.
struct Basis
{
@@ -1197,40 +1331,34 @@ public:
m_wordArray.resize((m_size + 31) >> 5);
}
- /// Get bit.
- bool bitAt(uint32_t b) const
+ bool get(uint32_t index) const
{
- XA_DEBUG_ASSERT( b < m_size );
- return (m_wordArray[b >> 5] & (1 << (b & 31))) != 0;
+ XA_DEBUG_ASSERT(index < m_size);
+ return (m_wordArray[index >> 5] & (1 << (index & 31))) != 0;
}
- // Set a bit.
- void setBitAt(uint32_t idx)
+ void set(uint32_t index)
{
- XA_DEBUG_ASSERT(idx < m_size);
- m_wordArray[idx >> 5] |= (1 << (idx & 31));
+ XA_DEBUG_ASSERT(index < m_size);
+ m_wordArray[index >> 5] |= (1 << (index & 31));
}
- // Clear all the bits.
- void clearAll()
+ void zeroOutMemory()
{
- memset(m_wordArray.data(), 0, m_wordArray.size() * sizeof(uint32_t));
+ m_wordArray.zeroOutMemory();
}
private:
- // Number of bits stored.
- uint32_t m_size;
-
- // Array of bits.
+ uint32_t m_size; // Number of bits stored.
Array<uint32_t> m_wordArray;
};
class BitImage
{
public:
- BitImage() : m_width(0), m_height(0), m_rowStride(0) {}
+ BitImage() : m_width(0), m_height(0), m_rowStride(0), m_data(MemTag::BitImage) {}
- BitImage(uint32_t w, uint32_t h) : m_width(w), m_height(h)
+ BitImage(uint32_t w, uint32_t h) : m_width(w), m_height(h), m_data(MemTag::BitImage)
{
m_rowStride = (m_width + 63) >> 6;
m_data.resize(m_rowStride * m_height);
@@ -1238,7 +1366,7 @@ public:
}
BitImage(const BitImage &other) = delete;
- const BitImage &operator=(const BitImage &other) = delete;
+ BitImage &operator=(const BitImage &other) = delete;
uint32_t width() const { return m_width; }
uint32_t height() const { return m_height; }
@@ -1275,22 +1403,22 @@ public:
m_rowStride = rowStride;
}
- bool bitAt(uint32_t x, uint32_t y) const
+ bool get(uint32_t x, uint32_t y) const
{
XA_DEBUG_ASSERT(x < m_width && y < m_height);
const uint32_t index = (x >> 6) + y * m_rowStride;
return (m_data[index] & (UINT64_C(1) << (uint64_t(x) & UINT64_C(63)))) != 0;
}
- void setBitAt(uint32_t x, uint32_t y)
+ void set(uint32_t x, uint32_t y)
{
XA_DEBUG_ASSERT(x < m_width && y < m_height);
const uint32_t index = (x >> 6) + y * m_rowStride;
m_data[index] |= UINT64_C(1) << (uint64_t(x) & UINT64_C(63));
- XA_DEBUG_ASSERT(bitAt(x, y));
+ XA_DEBUG_ASSERT(get(x, y));
}
- void clearAll()
+ void zeroOutMemory()
{
m_data.zeroOutMemory();
}
@@ -1324,26 +1452,26 @@ public:
{
BitImage tmp(m_width, m_height);
for (uint32_t p = 0; p < padding; p++) {
- tmp.clearAll();
+ tmp.zeroOutMemory();
for (uint32_t y = 0; y < m_height; y++) {
for (uint32_t x = 0; x < m_width; x++) {
- bool b = bitAt(x, y);
+ bool b = get(x, y);
if (!b) {
if (x > 0) {
- b |= bitAt(x - 1, y);
- if (y > 0) b |= bitAt(x - 1, y - 1);
- if (y < m_height - 1) b |= bitAt(x - 1, y + 1);
+ b |= get(x - 1, y);
+ if (y > 0) b |= get(x - 1, y - 1);
+ if (y < m_height - 1) b |= get(x - 1, y + 1);
}
- if (y > 0) b |= bitAt(x, y - 1);
- if (y < m_height - 1) b |= bitAt(x, y + 1);
+ if (y > 0) b |= get(x, y - 1);
+ if (y < m_height - 1) b |= get(x, y + 1);
if (x < m_width - 1) {
- b |= bitAt(x + 1, y);
- if (y > 0) b |= bitAt(x + 1, y - 1);
- if (y < m_height - 1) b |= bitAt(x + 1, y + 1);
+ b |= get(x + 1, y);
+ if (y > 0) b |= get(x + 1, y - 1);
+ if (y < m_height - 1) b |= get(x + 1, y + 1);
}
}
if (b)
- tmp.setBitAt(x, y);
+ tmp.set(x, y);
}
}
tmp.m_data.copyTo(m_data);
@@ -1361,7 +1489,7 @@ private:
class BVH
{
public:
- BVH(const Array<AABB> &objectAabbs, uint32_t leafSize = 4)
+ BVH(const Array<AABB> &objectAabbs, uint32_t leafSize = 4) : m_objectIds(MemTag::BVH), m_nodes(MemTag::BVH)
{
m_objectAabbs = &objectAabbs;
if (m_objectAabbs->isEmpty())
@@ -1494,9 +1622,118 @@ private:
Array<Node> m_nodes;
};
-class Fit
+struct Fit
{
-public:
+ static bool computeBasis(const Vector3 *points, uint32_t pointsCount, Basis *basis)
+ {
+ if (computeLeastSquaresNormal(points, pointsCount, &basis->normal)) {
+ basis->tangent = Basis::computeTangent(basis->normal);
+ basis->bitangent = Basis::computeBitangent(basis->normal, basis->tangent);
+ return true;
+ }
+ return computeEigen(points, pointsCount, basis);
+ }
+
+private:
+ // Fit a plane to a collection of points.
+ // Fast, and accurate to within a few degrees.
+ // Returns None if the points do not span a plane.
+ // https://www.ilikebigbits.com/2015_03_04_plane_from_points.html
+ static bool computeLeastSquaresNormal(const Vector3 *points, uint32_t pointsCount, Vector3 *normal)
+ {
+ XA_DEBUG_ASSERT(pointsCount >= 3);
+ if (pointsCount == 3) {
+ *normal = normalize(cross(points[2] - points[0], points[1] - points[0]), kEpsilon);
+ return true;
+ }
+ const float invN = 1.0f / float(pointsCount);
+ Vector3 centroid(0.0f);
+ for (uint32_t i = 0; i < pointsCount; i++)
+ centroid += points[i];
+ centroid *= invN;
+ // Calculate full 3x3 covariance matrix, excluding symmetries:
+ float xx = 0.0f, xy = 0.0f, xz = 0.0f, yy = 0.0f, yz = 0.0f, zz = 0.0f;
+ for (uint32_t i = 0; i < pointsCount; i++) {
+ Vector3 r = points[i] - centroid;
+ xx += r.x * r.x;
+ xy += r.x * r.y;
+ xz += r.x * r.z;
+ yy += r.y * r.y;
+ yz += r.y * r.z;
+ zz += r.z * r.z;
+ }
+#if 0
+ xx *= invN;
+ xy *= invN;
+ xz *= invN;
+ yy *= invN;
+ yz *= invN;
+ zz *= invN;
+ Vector3 weighted_dir(0.0f);
+ {
+ float det_x = yy * zz - yz * yz;
+ const Vector3 axis_dir(det_x, xz * yz - xy * zz, xy * yz - xz * yy);
+ float weight = det_x * det_x;
+ if (dot(weighted_dir, axis_dir) < 0.0f)
+ weight = -weight;
+ weighted_dir += axis_dir * weight;
+ }
+ {
+ float det_y = xx * zz - xz * xz;
+ const Vector3 axis_dir(xz * yz - xy * zz, det_y, xy * xz - yz * xx);
+ float weight = det_y * det_y;
+ if (dot(weighted_dir, axis_dir) < 0.0f)
+ weight = -weight;
+ weighted_dir += axis_dir * weight;
+ }
+ {
+ float det_z = xx * yy - xy * xy;
+ const Vector3 axis_dir(xy * yz - xz * yy, xy * xz - yz * xx, det_z);
+ float weight = det_z * det_z;
+ if (dot(weighted_dir, axis_dir) < 0.0f)
+ weight = -weight;
+ weighted_dir += axis_dir * weight;
+ }
+ *normal = normalize(weighted_dir, kEpsilon);
+#else
+ const float det_x = yy * zz - yz * yz;
+ const float det_y = xx * zz - xz * xz;
+ const float det_z = xx * yy - xy * xy;
+ const float det_max = max(det_x, max(det_y, det_z));
+ if (det_max <= 0.0f)
+ return false; // The points don't span a plane
+ // Pick path with best conditioning:
+ Vector3 dir(0.0f);
+ if (det_max == det_x)
+ dir = Vector3(det_x,xz * yz - xy * zz,xy * yz - xz * yy);
+ else if (det_max == det_y)
+ dir = Vector3(xz * yz - xy * zz, det_y, xy * xz - yz * xx);
+ else if (det_max == det_z)
+ dir = Vector3(xy * yz - xz * yy, xy * xz - yz * xx, det_z);
+ const float len = length(dir);
+ if (isZero(len, kEpsilon))
+ return false;
+ *normal = dir * (1.0f / len);
+#endif
+ return isNormalized(*normal);
+ }
+
+ static bool computeEigen(const Vector3 *points, uint32_t pointsCount, Basis *basis)
+ {
+ float matrix[6];
+ computeCovariance(pointsCount, points, matrix);
+ if (matrix[0] == 0 && matrix[3] == 0 && matrix[5] == 0)
+ return false;
+ float eigenValues[3];
+ Vector3 eigenVectors[3];
+ if (!eigenSolveSymmetric3(matrix, eigenValues, eigenVectors))
+ return false;
+ basis->normal = normalize(eigenVectors[2], kEpsilon);
+ basis->tangent = normalize(eigenVectors[0], kEpsilon);
+ basis->bitangent = normalize(eigenVectors[1], kEpsilon);
+ return true;
+ }
+
static Vector3 computeCentroid(int n, const Vector3 * points)
{
Vector3 centroid(0.0f);
@@ -1694,9 +1931,9 @@ private:
class FullVector
{
public:
- FullVector(uint32_t dim) { m_array.resize(dim); }
- FullVector(const FullVector &v) { v.m_array.copyTo(m_array); }
- const FullVector &operator=(const FullVector &v) = delete;
+ FullVector(uint32_t dim) : m_array(MemTag::FullVector) { m_array.resize(dim); }
+ FullVector(const FullVector &v) : m_array(MemTag::FullVector) { v.m_array.copyTo(m_array); }
+ FullVector &operator=(const FullVector &v) = delete;
XA_INLINE uint32_t dimension() const { return m_array.size(); }
XA_INLINE const float &operator[](uint32_t index) const { return m_array[index]; }
XA_INLINE float &operator[](uint32_t index) { return m_array[index]; }
@@ -1767,7 +2004,10 @@ private:
void alloc()
{
XA_DEBUG_ASSERT(m_size > 0);
- m_numSlots = (uint32_t)(m_size * 1.3);
+ m_numSlots = nextPowerOfTwo(m_size);
+ auto minNumSlots = uint32_t(m_size * 1.3);
+ if (m_numSlots < minNumSlots)
+ m_numSlots = nextPowerOfTwo(minNumSlots);
m_slots = XA_ALLOC_ARRAY(m_memTag, uint32_t, m_numSlots);
for (uint32_t i = 0; i < m_numSlots; i++)
m_slots[i] = UINT32_MAX;
@@ -1778,7 +2018,7 @@ private:
uint32_t computeHash(const Key &key) const
{
H hash;
- return hash(key) % m_numSlots;
+ return hash(key) & (m_numSlots - 1);
}
int m_memTag;
@@ -1806,6 +2046,16 @@ static void insertionSort(T *data, uint32_t length)
class KISSRng
{
public:
+ KISSRng() { reset(); }
+
+ void reset()
+ {
+ x = 123456789;
+ y = 362436000;
+ z = 521288629;
+ c = 7654321;
+ }
+
uint32_t getRange(uint32_t range)
{
if (range == 0)
@@ -1820,7 +2070,7 @@ public:
}
private:
- uint32_t x = 123456789, y = 362436000, z = 521288629, c = 7654321;
+ uint32_t x, y, z, c;
};
// Based on Pierre Terdiman's and Michael Herf's source code.
@@ -2009,15 +2259,27 @@ private:
class BoundingBox2D
{
public:
- Vector2 majorAxis() const { return m_majorAxis; }
- Vector2 minorAxis() const { return m_minorAxis; }
- Vector2 minCorner() const { return m_minCorner; }
- Vector2 maxCorner() const { return m_maxCorner; }
+ Vector2 majorAxis, minorAxis, minCorner, maxCorner;
+
+ void clear()
+ {
+ m_boundaryVertices.clear();
+ }
+
+ void appendBoundaryVertex(Vector2 v)
+ {
+ m_boundaryVertices.push_back(v);
+ }
// This should compute convex hull and use rotating calipers to find the best box. Currently it uses a brute force method.
- void compute(const Vector2 *boundaryVertices, uint32_t boundaryVertexCount, const Vector2 *vertices, uint32_t vertexCount)
+ // If vertices is null or vertexCount is 0, the boundary vertices are used.
+ void compute(const Vector2 *vertices = nullptr, uint32_t vertexCount = 0)
{
- convexHull(boundaryVertices, boundaryVertexCount, m_hull, 0.00001f);
+ if (!vertices || vertexCount == 0) {
+ vertices = m_boundaryVertices.data();
+ vertexCount = m_boundaryVertices.size();
+ }
+ convexHull(m_boundaryVertices.data(), m_boundaryVertices.size(), m_hull, 0.00001f);
// @@ Ideally I should use rotating calipers to find the best box. Using brute force for now.
float best_area = FLT_MAX;
Vector2 best_min(0);
@@ -2051,11 +2313,11 @@ public:
best_axis = axis;
}
}
- m_majorAxis = best_axis;
- m_minorAxis = Vector2(-best_axis.y, best_axis.x);
- m_minCorner = best_min;
- m_maxCorner = best_max;
- XA_ASSERT(isFinite(m_majorAxis) && isFinite(m_minorAxis) && isFinite(m_minCorner));
+ majorAxis = best_axis;
+ minorAxis = Vector2(-best_axis.y, best_axis.x);
+ minCorner = best_min;
+ maxCorner = best_max;
+ XA_ASSERT(isFinite(majorAxis) && isFinite(minorAxis) && isFinite(minCorner));
}
private:
@@ -2088,6 +2350,7 @@ private:
}
// Filter top list.
output.clear();
+ XA_DEBUG_ASSERT(m_top.size() >= 2);
output.push_back(m_top[0]);
output.push_back(m_top[1]);
for (uint32_t i = 2; i < m_top.size(); ) {
@@ -2103,6 +2366,7 @@ private:
}
}
uint32_t top_count = output.size();
+ XA_DEBUG_ASSERT(m_bottom.size() >= 2);
output.push_back(m_bottom[1]);
// Filter bottom list.
for (uint32_t i = 2; i < m_bottom.size(); ) {
@@ -2122,9 +2386,9 @@ private:
output.pop_back();
}
+ Array<Vector2> m_boundaryVertices;
Array<float> m_coords;
Array<Vector2> m_top, m_bottom, m_hull;
- Vector2 m_majorAxis, m_minorAxis, m_minCorner, m_maxCorner;
};
static uint32_t meshEdgeFace(uint32_t edge) { return edge / 3; }
@@ -2152,7 +2416,7 @@ static void meshGetBoundaryLoops(const Mesh &mesh, Array<uint32_t> &boundaryLoop
class Mesh
{
public:
- Mesh(float epsilon, uint32_t approxVertexCount, uint32_t approxFaceCount, uint32_t flags = 0, uint32_t id = UINT32_MAX) : m_epsilon(epsilon), m_flags(flags), m_id(id), m_faceIgnore(MemTag::Mesh), m_faceGroups(MemTag::Mesh), m_indices(MemTag::MeshIndices), m_positions(MemTag::MeshPositions), m_normals(MemTag::MeshNormals), m_texcoords(MemTag::MeshTexcoords), m_colocalVertexCount(0), m_nextColocalVertex(MemTag::MeshColocals), m_boundaryVertices(MemTag::MeshBoundaries), m_oppositeEdges(MemTag::MeshBoundaries), m_nextBoundaryEdges(MemTag::MeshBoundaries), m_edgeMap(MemTag::MeshEdgeMap, approxFaceCount * 3)
+ Mesh(float epsilon, uint32_t approxVertexCount, uint32_t approxFaceCount, uint32_t flags = 0, uint32_t id = UINT32_MAX) : m_epsilon(epsilon), m_flags(flags), m_id(id), m_faceIgnore(MemTag::Mesh), m_ignoredFaceCount(0), m_indices(MemTag::MeshIndices), m_positions(MemTag::MeshPositions), m_normals(MemTag::MeshNormals), m_texcoords(MemTag::MeshTexcoords), m_faceGroups(MemTag::Mesh), m_faceGroupFirstFace(MemTag::Mesh), m_faceGroupNextFace(MemTag::Mesh), m_faceGroupFaceCounts(MemTag::Mesh), m_colocalVertexCount(0), m_nextColocalVertex(MemTag::MeshColocals), m_boundaryEdges(MemTag::MeshBoundaries), m_oppositeEdges(MemTag::MeshBoundaries), m_nextBoundaryEdges(MemTag::MeshBoundaries), m_edgeMap(MemTag::MeshEdgeMap, approxFaceCount * 3)
{
m_indices.reserve(approxFaceCount * 3);
m_positions.reserve(approxVertexCount);
@@ -2165,6 +2429,7 @@ public:
m_normals.reserve(approxVertexCount);
}
+ static constexpr uint16_t kInvalidFaceGroup = UINT16_MAX;
uint32_t flags() const { return m_flags; }
uint32_t id() const { return m_id; }
@@ -2199,9 +2464,12 @@ public:
{
AddFaceResult::Enum result = AddFaceResult::OK;
if (m_flags & MeshFlags::HasFaceGroups)
- m_faceGroups.push_back(UINT32_MAX);
- if (m_flags & MeshFlags::HasIgnoredFaces)
+ m_faceGroups.push_back(kInvalidFaceGroup);
+ if (m_flags & MeshFlags::HasIgnoredFaces) {
m_faceIgnore.push_back(ignore);
+ if (ignore)
+ m_ignoredFaceCount++;
+ }
const uint32_t firstIndex = m_indices.size();
for (uint32_t i = 0; i < 3; i++)
m_indices.push_back(indices[i]);
@@ -2221,13 +2489,13 @@ public:
void createColocals()
{
const uint32_t vertexCount = m_positions.size();
- Array<AABB> aabbs;
+ Array<AABB> aabbs(MemTag::BVH);
aabbs.resize(vertexCount);
for (uint32_t i = 0; i < m_positions.size(); i++)
aabbs[i] = AABB(m_positions[i], m_epsilon);
BVH bvh(aabbs);
- Array<uint32_t> colocals;
- Array<uint32_t> potential;
+ Array<uint32_t> colocals(MemTag::MeshColocals);
+ Array<uint32_t> potential(MemTag::MeshColocals);
m_colocalVertexCount = 0;
m_nextColocalVertex.resize(vertexCount);
for (uint32_t i = 0; i < vertexCount; i++)
@@ -2259,7 +2527,7 @@ public:
}
// Check if the face duplicates any edges of any face already in the group.
- bool faceDuplicatesGroupEdge(uint32_t group, uint32_t face) const
+ bool faceDuplicatesGroupEdge(uint16_t group, uint32_t face) const
{
for (FaceEdgeIterator edgeIt(this, face); !edgeIt.isDone(); edgeIt.advance()) {
for (ColocalEdgeIterator colocalEdgeIt(this, edgeIt.vertex0(), edgeIt.vertex1()); !colocalEdgeIt.isDone(); colocalEdgeIt.advance()) {
@@ -2270,55 +2538,31 @@ public:
return false;
}
- // Check if the face mirrors any face already in the group.
- // i.e. don't want two-sided faces in the same group.
- // A face mirrors another face if all edges match with opposite winding.
- bool faceMirrorsGroupFace(uint32_t group, uint32_t face) const
- {
- FaceEdgeIterator edgeIt(this, face);
- for (ColocalEdgeIterator colocalEdgeIt(this, edgeIt.vertex1(), edgeIt.vertex0()); !colocalEdgeIt.isDone(); colocalEdgeIt.advance()) {
- const uint32_t candidateFace = meshEdgeFace(colocalEdgeIt.edge());
- if (m_faceGroups[candidateFace] == group) {
- // Found a match for mirrored first edge, try the other edges.
- bool match = false;
- for (; !edgeIt.isDone(); edgeIt.advance()) {
- match = false;
- for (ColocalEdgeIterator colocalEdgeIt2(this, edgeIt.vertex1(), edgeIt.vertex0()); !colocalEdgeIt2.isDone(); colocalEdgeIt2.advance()) {
- if (meshEdgeFace(colocalEdgeIt2.edge()) == candidateFace) {
- match = true;
- break;
- }
- }
- if (!match)
- break;
- }
- if (match)
- return true; // All edges are mirrored in this face.
- // Try the next face.
- edgeIt = FaceEdgeIterator(this, candidateFace);
- }
- }
- return false;
- }
-
void createFaceGroups()
{
- uint32_t group = 0;
+ uint32_t firstUnassignedFace = 0;
+ uint16_t group = 0;
Array<uint32_t> growFaces;
+ const uint32_t n = faceCount();
+ m_faceGroupNextFace.resize(n);
for (;;) {
// Find an unassigned face.
uint32_t face = UINT32_MAX;
- for (uint32_t f = 0; f < faceCount(); f++) {
- if (m_faceGroups[f] == UINT32_MAX && !isFaceIgnored(f)) {
+ for (uint32_t f = firstUnassignedFace; f < n; f++) {
+ if (m_faceGroups[f] == kInvalidFaceGroup && !isFaceIgnored(f)) {
face = f;
+ firstUnassignedFace = f + 1;
break;
}
}
if (face == UINT32_MAX)
break; // All faces assigned to a group (except ignored faces).
m_faceGroups[face] = group;
+ m_faceGroupNextFace[face] = UINT32_MAX;
+ m_faceGroupFirstFace.push_back(face);
growFaces.clear();
growFaces.push_back(face);
+ uint32_t prevFace = face, groupFaceCount = 1;
// Find faces connected to the face and assign them to the same group as the face, unless they are already assigned to another group.
for (;;) {
if (growFaces.isEmpty())
@@ -2340,24 +2584,38 @@ public:
alreadyAssignedToThisGroup = true;
break;
}
- if (m_faceGroups[oppositeFace] != UINT32_MAX)
+ if (m_faceGroups[oppositeFace] != kInvalidFaceGroup)
continue; // Connected face is already assigned to another group.
if (faceDuplicatesGroupEdge(group, oppositeFace))
continue; // Don't want duplicate edges in a group.
- if (faceMirrorsGroupFace(group, oppositeFace))
- continue; // Don't want two-sided faces in a group.
const uint32_t oppositeVertex0 = m_indices[meshEdgeIndex0(oppositeEdge)];
const uint32_t oppositeVertex1 = m_indices[meshEdgeIndex1(oppositeEdge)];
if (bestConnectedFace == UINT32_MAX || (oppositeVertex0 == edgeIt.vertex1() && oppositeVertex1 == edgeIt.vertex0()))
bestConnectedFace = oppositeFace;
+#if 0
+ else {
+ // Choose the opposite face with the smallest dihedral angle.
+ const float d1 = 1.0f - dot(computeFaceNormal(f), computeFaceNormal(bestConnectedFace));
+ const float d2 = 1.0f - dot(computeFaceNormal(f), computeFaceNormal(oppositeFace));
+ if (d2 < d1)
+ bestConnectedFace = oppositeFace;
+ }
+#endif
}
if (!alreadyAssignedToThisGroup && bestConnectedFace != UINT32_MAX) {
m_faceGroups[bestConnectedFace] = group;
+ m_faceGroupNextFace[bestConnectedFace] = UINT32_MAX;
+ if (prevFace != UINT32_MAX)
+ m_faceGroupNextFace[prevFace] = bestConnectedFace;
+ prevFace = bestConnectedFace;
+ groupFaceCount++;
growFaces.push_back(bestConnectedFace);
}
}
}
+ m_faceGroupFaceCounts.push_back(groupFaceCount);
group++;
+ XA_ASSERT(group < kInvalidFaceGroup);
}
}
@@ -2366,29 +2624,27 @@ public:
const uint32_t edgeCount = m_indices.size();
const uint32_t vertexCount = m_positions.size();
m_oppositeEdges.resize(edgeCount);
- m_boundaryVertices.resize(vertexCount);
+ m_boundaryEdges.reserve(uint32_t(edgeCount * 0.1f));
+ m_isBoundaryVertex.resize(vertexCount);
+ m_isBoundaryVertex.zeroOutMemory();
for (uint32_t i = 0; i < edgeCount; i++)
m_oppositeEdges[i] = UINT32_MAX;
- for (uint32_t i = 0; i < vertexCount; i++)
- m_boundaryVertices[i] = false;
- const bool hasFaceGroups = m_flags & MeshFlags::HasFaceGroups;
- for (uint32_t i = 0; i < faceCount(); i++) {
+ const uint32_t faceCount = m_indices.size() / 3;
+ for (uint32_t i = 0; i < faceCount; i++) {
if (isFaceIgnored(i))
continue;
for (uint32_t j = 0; j < 3; j++) {
- const uint32_t vertex0 = m_indices[i * 3 + j];
+ const uint32_t edge = i * 3 + j;
+ const uint32_t vertex0 = m_indices[edge];
const uint32_t vertex1 = m_indices[i * 3 + (j + 1) % 3];
// If there is an edge with opposite winding to this one, the edge isn't on a boundary.
- const uint32_t oppositeEdge = findEdge(hasFaceGroups ? m_faceGroups[i] : UINT32_MAX, vertex1, vertex0);
+ const uint32_t oppositeEdge = findEdge(vertex1, vertex0);
if (oppositeEdge != UINT32_MAX) {
-#if XA_DEBUG
- if (hasFaceGroups)
- XA_DEBUG_ASSERT(m_faceGroups[meshEdgeFace(oppositeEdge)] == m_faceGroups[i]);
-#endif
- XA_DEBUG_ASSERT(!isFaceIgnored(meshEdgeFace(oppositeEdge)));
- m_oppositeEdges[i * 3 + j] = oppositeEdge;
+ m_oppositeEdges[edge] = oppositeEdge;
} else {
- m_boundaryVertices[vertex0] = m_boundaryVertices[vertex1] = true;
+ m_boundaryEdges.push_back(edge);
+ m_isBoundaryVertex.set(vertex0);
+ m_isBoundaryVertex.set(vertex1);
}
}
}
@@ -2407,12 +2663,12 @@ public:
m_nextBoundaryEdges[i] = UINT32_MAX;
uint32_t numBoundaryLoops = 0, numUnclosedBoundaries = 0;
BitArray linkedEdges(edgeCount);
- linkedEdges.clearAll();
+ linkedEdges.zeroOutMemory();
for (;;) {
// Find the first boundary edge that hasn't been linked yet.
uint32_t firstEdge = UINT32_MAX;
for (uint32_t i = 0; i < edgeCount; i++) {
- if (m_oppositeEdges[i] == UINT32_MAX && !linkedEdges.bitAt(i)) {
+ if (m_oppositeEdges[i] == UINT32_MAX && !linkedEdges.get(i)) {
firstEdge = i;
break;
}
@@ -2430,12 +2686,8 @@ public:
const uint32_t otherEdge = mapIndex / 2; // Two vertices added per edge.
if (m_oppositeEdges[otherEdge] != UINT32_MAX)
goto next; // Not a boundary edge.
- if (linkedEdges.bitAt(otherEdge))
+ if (linkedEdges.get(otherEdge))
goto next; // Already linked.
- if (m_flags & MeshFlags::HasFaceGroups && m_faceGroups[meshEdgeFace(currentEdge)] != m_faceGroups[meshEdgeFace(otherEdge)])
- goto next; // Don't cross face groups.
- if (isFaceIgnored(meshEdgeFace(otherEdge)))
- goto next; // Face is ignored.
if (m_indices[meshEdgeIndex0(otherEdge)] != it.vertex())
goto next; // Edge contains the vertex, but it's the wrong one.
// First edge (closing the boundary loop) has the highest priority.
@@ -2449,11 +2701,11 @@ public:
if (bestNextEdge == UINT32_MAX) {
numUnclosedBoundaries++;
if (currentEdge == firstEdge)
- linkedEdges.setBitAt(firstEdge); // Only 1 edge in this boundary "loop".
+ linkedEdges.set(firstEdge); // Only 1 edge in this boundary "loop".
break; // Can't find a next edge.
}
m_nextBoundaryEdges[currentEdge] = bestNextEdge;
- linkedEdges.setBitAt(bestNextEdge);
+ linkedEdges.set(bestNextEdge);
currentEdge = bestNextEdge;
if (currentEdge == firstEdge) {
numBoundaryLoops++;
@@ -2461,6 +2713,7 @@ public:
}
}
}
+#if XA_FIX_INTERNAL_BOUNDARY_LOOPS
// Find internal boundary loops and separate them.
// Detect by finding two edges in a boundary loop that have a colocal end vertex.
// Fix by swapping their next boundary edge.
@@ -2469,28 +2722,29 @@ public:
fixInternalBoundary:
meshGetBoundaryLoops(*this, boundaryLoops);
for (uint32_t loop = 0; loop < boundaryLoops.size(); loop++) {
- linkedEdges.clearAll();
- for (Mesh::BoundaryEdgeIterator it1(this, boundaryLoops[loop]); !it1.isDone(); it1.advance()) {
+ linkedEdges.zeroOutMemory();
+ for (Mesh::BoundaryLoopEdgeIterator it1(this, boundaryLoops[loop]); !it1.isDone(); it1.advance()) {
const uint32_t e1 = it1.edge();
- if (linkedEdges.bitAt(e1))
+ if (linkedEdges.get(e1))
continue;
- for (Mesh::BoundaryEdgeIterator it2(this, boundaryLoops[loop]); !it2.isDone(); it2.advance()) {
+ for (Mesh::BoundaryLoopEdgeIterator it2(this, boundaryLoops[loop]); !it2.isDone(); it2.advance()) {
const uint32_t e2 = it2.edge();
- if (e1 == e2 || !isBoundaryEdge(e2) || linkedEdges.bitAt(e2))
+ if (e1 == e2 || !isBoundaryEdge(e2) || linkedEdges.get(e2))
continue;
if (!areColocal(m_indices[meshEdgeIndex1(e1)], m_indices[meshEdgeIndex1(e2)]))
continue;
swap(m_nextBoundaryEdges[e1], m_nextBoundaryEdges[e2]);
- linkedEdges.setBitAt(e1);
- linkedEdges.setBitAt(e2);
+ linkedEdges.set(e1);
+ linkedEdges.set(e2);
goto fixInternalBoundary; // start over
}
}
}
+#endif
}
/// Find edge, test all colocals.
- uint32_t findEdge(uint32_t faceGroup, uint32_t vertex0, uint32_t vertex1) const
+ uint32_t findEdge(uint32_t vertex0, uint32_t vertex1) const
{
uint32_t result = UINT32_MAX;
if (m_nextColocalVertex.isEmpty()) {
@@ -2498,7 +2752,7 @@ public:
uint32_t edge = m_edgeMap.get(key);
while (edge != UINT32_MAX) {
// Don't find edges of ignored faces.
- if ((faceGroup == UINT32_MAX || m_faceGroups[meshEdgeFace(edge)] == faceGroup) && !isFaceIgnored(meshEdgeFace(edge))) {
+ if (!isFaceIgnored(meshEdgeFace(edge))) {
//XA_DEBUG_ASSERT(m_id != UINT32_MAX || (m_id == UINT32_MAX && result == UINT32_MAX)); // duplicate edge - ignore on initial meshes
result = edge;
#if !XA_DEBUG
@@ -2514,7 +2768,7 @@ public:
uint32_t edge = m_edgeMap.get(key);
while (edge != UINT32_MAX) {
// Don't find edges of ignored faces.
- if ((faceGroup == UINT32_MAX || m_faceGroups[meshEdgeFace(edge)] == faceGroup) && !isFaceIgnored(meshEdgeFace(edge))) {
+ if (!isFaceIgnored(meshEdgeFace(edge))) {
XA_DEBUG_ASSERT(m_id != UINT32_MAX || (m_id == UINT32_MAX && result == UINT32_MAX)); // duplicate edge - ignore on initial meshes
result = edge;
#if !XA_DEBUG
@@ -2607,7 +2861,7 @@ public:
{
float area = 0;
for (uint32_t f = 0; f < faceCount(); f++)
- area += faceArea(f);
+ area += computeFaceArea(f);
XA_DEBUG_ASSERT(area >= 0);
return area;
}
@@ -2616,11 +2870,11 @@ public:
{
float area = 0;
for (uint32_t f = 0; f < faceCount(); f++)
- area += faceParametricArea(f);
+ area += computeFaceParametricArea(f);
return fabsf(area); // May be negative, depends on texcoord winding.
}
- float faceArea(uint32_t face) const
+ float computeFaceArea(uint32_t face) const
{
const Vector3 &p0 = m_positions[m_indices[face * 3 + 0]];
const Vector3 &p1 = m_positions[m_indices[face * 3 + 1]];
@@ -2628,7 +2882,7 @@ public:
return length(cross(p1 - p0, p2 - p0)) * 0.5f;
}
- Vector3 faceCentroid(uint32_t face) const
+ Vector3 computeFaceCentroid(uint32_t face) const
{
Vector3 sum(0.0f);
for (uint32_t i = 0; i < 3; i++)
@@ -2636,22 +2890,9 @@ public:
return sum / 3.0f;
}
- Vector3 calculateFaceNormal(uint32_t face) const
- {
- return normalizeSafe(triangleNormalAreaScaled(face), Vector3(0, 0, 1), 0.0f);
- }
-
- float faceParametricArea(uint32_t face) const
- {
- const Vector2 &t0 = m_texcoords[m_indices[face * 3 + 0]];
- const Vector2 &t1 = m_texcoords[m_indices[face * 3 + 1]];
- const Vector2 &t2 = m_texcoords[m_indices[face * 3 + 2]];
- return triangleArea(t0, t1, t2) * 0.5f;
- }
-
// Average of the edge midpoints weighted by the edge length.
// I want a point inside the triangle, but closer to the cirumcenter.
- Vector3 triangleCenter(uint32_t face) const
+ Vector3 computeFaceCenter(uint32_t face) const
{
const Vector3 &p0 = m_positions[m_indices[face * 3 + 0]];
const Vector3 &p1 = m_positions[m_indices[face * 3 + 1]];
@@ -2665,22 +2906,25 @@ public:
return m0 + m1 + m2;
}
- // Unnormalized face normal assuming it's a triangle.
- Vector3 triangleNormal(uint32_t face) const
- {
- return normalizeSafe(triangleNormalAreaScaled(face), Vector3(0), 0.0f);
- }
-
- Vector3 triangleNormalAreaScaled(uint32_t face) const
+ Vector3 computeFaceNormal(uint32_t face) const
{
const Vector3 &p0 = m_positions[m_indices[face * 3 + 0]];
const Vector3 &p1 = m_positions[m_indices[face * 3 + 1]];
const Vector3 &p2 = m_positions[m_indices[face * 3 + 2]];
const Vector3 e0 = p2 - p0;
const Vector3 e1 = p1 - p0;
- return cross(e0, e1);
+ const Vector3 normalAreaScaled = cross(e0, e1);
+ return normalizeSafe(normalAreaScaled, Vector3(0, 0, 1), 0.0f);
}
+ float computeFaceParametricArea(uint32_t face) const
+ {
+ const Vector2 &t0 = m_texcoords[m_indices[face * 3 + 0]];
+ const Vector2 &t1 = m_texcoords[m_indices[face * 3 + 1]];
+ const Vector2 &t2 = m_texcoords[m_indices[face * 3 + 2]];
+ return triangleArea(t0, t1, t2);
+ }
+
// @@ This is not exactly accurate, we should compare the texture coordinates...
bool isSeam(uint32_t edge) const
{
@@ -2732,7 +2976,8 @@ public:
XA_INLINE uint32_t edgeCount() const { return m_indices.size(); }
XA_INLINE uint32_t oppositeEdge(uint32_t edge) const { return m_oppositeEdges[edge]; }
XA_INLINE bool isBoundaryEdge(uint32_t edge) const { return m_oppositeEdges[edge] == UINT32_MAX; }
- XA_INLINE bool isBoundaryVertex(uint32_t vertex) const { return m_boundaryVertices[vertex]; }
+ XA_INLINE const Array<uint32_t> &boundaryEdges() const { return m_boundaryEdges; }
+ XA_INLINE bool isBoundaryVertex(uint32_t vertex) const { return m_isBoundaryVertex.get(vertex); }
XA_INLINE uint32_t colocalVertexCount() const { return m_colocalVertexCount; }
XA_INLINE uint32_t vertexCount() const { return m_positions.size(); }
XA_INLINE uint32_t vertexAt(uint32_t i) const { return m_indices[i]; }
@@ -2740,10 +2985,14 @@ public:
XA_INLINE const Vector3 &normal(uint32_t vertex) const { XA_DEBUG_ASSERT(m_flags & MeshFlags::HasNormals); return m_normals[vertex]; }
XA_INLINE const Vector2 &texcoord(uint32_t vertex) const { return m_texcoords[vertex]; }
XA_INLINE Vector2 &texcoord(uint32_t vertex) { return m_texcoords[vertex]; }
+ XA_INLINE const Vector2 *texcoords() const { return m_texcoords.data(); }
XA_INLINE Vector2 *texcoords() { return m_texcoords.data(); }
+ XA_INLINE uint32_t ignoredFaceCount() const { return m_ignoredFaceCount; }
XA_INLINE uint32_t faceCount() const { return m_indices.size() / 3; }
- XA_INLINE uint32_t faceGroupCount() const { XA_DEBUG_ASSERT(m_flags & MeshFlags::HasFaceGroups); return m_faceGroups.size(); }
- XA_INLINE uint32_t faceGroupAt(uint32_t face) const { XA_DEBUG_ASSERT(m_flags & MeshFlags::HasFaceGroups); return m_faceGroups[face]; }
+ XA_INLINE uint16_t faceGroupAt(uint32_t face) const { XA_DEBUG_ASSERT(m_flags & MeshFlags::HasFaceGroups); return m_faceGroups[face]; }
+ XA_INLINE uint32_t faceGroupCount() const { XA_DEBUG_ASSERT(m_flags & MeshFlags::HasFaceGroups); return m_faceGroupFaceCounts.size(); }
+ XA_INLINE uint32_t faceGroupNextFace(uint32_t face) const { XA_DEBUG_ASSERT(m_flags & MeshFlags::HasFaceGroups); return m_faceGroupNextFace[face]; }
+ XA_INLINE uint32_t faceGroupFaceCount(uint32_t group) const { XA_DEBUG_ASSERT(m_flags & MeshFlags::HasFaceGroups); return m_faceGroupFaceCounts[group]; }
XA_INLINE const uint32_t *indices() const { return m_indices.data(); }
XA_INLINE uint32_t indexCount() const { return m_indices.size(); }
@@ -2754,18 +3003,25 @@ private:
uint32_t m_flags;
uint32_t m_id;
Array<bool> m_faceIgnore;
- Array<uint32_t> m_faceGroups;
+ uint32_t m_ignoredFaceCount;
Array<uint32_t> m_indices;
Array<Vector3> m_positions;
Array<Vector3> m_normals;
Array<Vector2> m_texcoords;
+ // Populated by createFaceGroups
+ Array<uint16_t> m_faceGroups;
+ Array<uint32_t> m_faceGroupFirstFace;
+ Array<uint32_t> m_faceGroupNextFace; // In: face. Out: the next face in the same group.
+ Array<uint32_t> m_faceGroupFaceCounts; // In: face group. Out: number of faces in the group.
+
// Populated by createColocals
uint32_t m_colocalVertexCount;
Array<uint32_t> m_nextColocalVertex; // In: vertex index. Out: the vertex index of the next colocal position.
// Populated by createBoundaries
- Array<bool> m_boundaryVertices;
+ BitArray m_isBoundaryVertex;
+ Array<uint32_t> m_boundaryEdges;
Array<uint32_t> m_oppositeEdges; // In: edge index. Out: the index of the opposite edge (i.e. wound the opposite direction). UINT32_MAX if the input edge is a boundary edge.
// Populated by linkBoundaries
@@ -2776,28 +3032,24 @@ private:
EdgeKey() {}
EdgeKey(const EdgeKey &k) : v0(k.v0), v1(k.v1) {}
EdgeKey(uint32_t v0, uint32_t v1) : v0(v0), v1(v1) {}
-
- void operator=(const EdgeKey &k)
- {
- v0 = k.v0;
- v1 = k.v1;
- }
- bool operator==(const EdgeKey &k) const
- {
- return v0 == k.v0 && v1 == k.v1;
- }
+ bool operator==(const EdgeKey &k) const { return v0 == k.v0 && v1 == k.v1; }
uint32_t v0;
uint32_t v1;
};
- HashMap<EdgeKey> m_edgeMap;
+ struct EdgeHash
+ {
+ uint32_t operator()(const EdgeKey &k) const { return k.v0 * 32768u + k.v1; }
+ };
+
+ HashMap<EdgeKey, EdgeHash> m_edgeMap;
public:
- class BoundaryEdgeIterator
+ class BoundaryLoopEdgeIterator
{
public:
- BoundaryEdgeIterator(const Mesh *mesh, uint32_t edge) : m_mesh(mesh), m_first(UINT32_MAX), m_current(edge) {}
+ BoundaryLoopEdgeIterator(const Mesh *mesh, uint32_t edge) : m_mesh(mesh), m_first(UINT32_MAX), m_current(edge) {}
void advance()
{
@@ -2866,7 +3118,14 @@ public:
public:
ColocalEdgeIterator(const Mesh *mesh, uint32_t vertex0, uint32_t vertex1) : m_mesh(mesh), m_vertex0It(mesh, vertex0), m_vertex1It(mesh, vertex1), m_vertex1(vertex1)
{
- resetElement();
+ do {
+ if (!resetElement()) {
+ advanceVertex1();
+ }
+ else {
+ break;
+ }
+ } while (!isDone());
}
void advance()
@@ -2885,7 +3144,7 @@ public:
}
private:
- void resetElement()
+ bool resetElement()
{
m_edge = m_mesh->m_edgeMap.get(Mesh::EdgeKey(m_vertex0It.vertex(), m_vertex1It.vertex()));
while (m_edge != UINT32_MAX) {
@@ -2893,8 +3152,10 @@ public:
break;
m_edge = m_mesh->m_edgeMap.getNext(m_edge);
}
- if (m_edge == UINT32_MAX)
- advanceVertex1();
+ if (m_edge == UINT32_MAX) {
+ return false;
+ }
+ return true;
}
void advanceElement()
@@ -2910,22 +3171,22 @@ public:
advanceVertex1();
}
- void advanceVertex0()
- {
- m_vertex0It.advance();
- if (m_vertex0It.isDone())
- return;
- m_vertex1It = ColocalVertexIterator(m_mesh, m_vertex1);
- resetElement();
- }
-
void advanceVertex1()
{
- m_vertex1It.advance();
- if (m_vertex1It.isDone())
- advanceVertex0();
- else
- resetElement();
+ auto successful = false;
+ while (!successful) {
+ m_vertex1It.advance();
+ if (m_vertex1It.isDone()) {
+ if (!m_vertex0It.isDone()) {
+ m_vertex0It.advance();
+ m_vertex1It = ColocalVertexIterator(m_mesh, m_vertex1);
+ }
+ else {
+ return;
+ }
+ }
+ successful = resetElement();
+ }
}
bool isIgnoredFace() const
@@ -2976,16 +3237,8 @@ public:
return meshEdgeFace(oedge);
}
- uint32_t vertex0() const
- {
- return m_mesh->m_indices[m_face * 3 + m_relativeEdge];
- }
-
- uint32_t vertex1() const
- {
- return m_mesh->m_indices[m_face * 3 + (m_relativeEdge + 1) % 3];
- }
-
+ uint32_t vertex0() const { return m_mesh->m_indices[m_face * 3 + m_relativeEdge]; }
+ uint32_t vertex1() const { return m_mesh->m_indices[m_face * 3 + (m_relativeEdge + 1) % 3]; }
const Vector3 &position0() const { return m_mesh->m_positions[vertex0()]; }
const Vector3 &position1() const { return m_mesh->m_positions[vertex1()]; }
const Vector3 &normal0() const { return m_mesh->m_normals[vertex0()]; }
@@ -2999,8 +3252,39 @@ public:
uint32_t m_edge;
uint32_t m_relativeEdge;
};
+
+ class GroupFaceIterator
+ {
+ public:
+ GroupFaceIterator(const Mesh *mesh, uint32_t group) : m_mesh(mesh)
+ {
+ XA_DEBUG_ASSERT(group != UINT32_MAX);
+ m_current = mesh->m_faceGroupFirstFace[group];
+ }
+
+ void advance()
+ {
+ m_current = m_mesh->m_faceGroupNextFace[m_current];
+ }
+
+ bool isDone() const
+ {
+ return m_current == UINT32_MAX;
+ }
+
+ uint32_t face() const
+ {
+ return m_current;
+ }
+
+ private:
+ const Mesh *m_mesh;
+ uint32_t m_current;
+ };
};
+constexpr uint16_t Mesh::kInvalidFaceGroup;
+
static bool meshCloseHole(Mesh *mesh, const Array<uint32_t> &holeVertices, const Vector3 &normal)
{
#if XA_CLOSE_HOLES_CHECK_EDGE_INTERSECTION
@@ -3027,15 +3311,15 @@ static bool meshCloseHole(Mesh *mesh, const Array<uint32_t> &holeVertices, const
const uint32_t i3 = (i + 1) % frontCount;
const Vector3 edge1 = frontPoints[i1] - frontPoints[i2];
const Vector3 edge2 = frontPoints[i3] - frontPoints[i2];
- frontAngles[i] = acosf(dot(edge1, edge2) / (length(edge1) * length(edge2)));
+ frontAngles[i] = atan2f(length(cross(edge1, edge2)), dot(edge1, edge2));
if (frontAngles[i] >= smallestAngle || isNan(frontAngles[i]))
continue;
// Don't duplicate edges.
- if (mesh->findEdge(UINT32_MAX, frontVertices[i1], frontVertices[i2]) != UINT32_MAX)
+ if (mesh->findEdge(frontVertices[i1], frontVertices[i2]) != UINT32_MAX)
continue;
- if (mesh->findEdge(UINT32_MAX, frontVertices[i2], frontVertices[i3]) != UINT32_MAX)
+ if (mesh->findEdge(frontVertices[i2], frontVertices[i3]) != UINT32_MAX)
continue;
- if (mesh->findEdge(UINT32_MAX, frontVertices[i3], frontVertices[i1]) != UINT32_MAX)
+ if (mesh->findEdge(frontVertices[i3], frontVertices[i1]) != UINT32_MAX)
continue;
/*
Make sure he new edge that would be formed by (i3, i1) doesn't intersect any vertices. This often happens when fixing t-junctions.
@@ -3128,9 +3412,10 @@ static bool meshCloseHole(Mesh *mesh, const Array<uint32_t> &holeVertices, const
return true;
}
-static bool meshCloseHoles(Mesh *mesh, const Array<uint32_t> &boundaryLoops, const Vector3 &normal, Array<uint32_t> &holeFaceCounts)
+static bool meshCloseHoles(Mesh *mesh, const Array<uint32_t> &boundaryLoops, const Vector3 &normal, uint32_t *holeCount, Array<uint32_t> *holeFaceCounts)
{
- holeFaceCounts.clear();
+ if (holeFaceCounts)
+ holeFaceCounts->clear();
// Compute lengths.
const uint32_t boundaryCount = boundaryLoops.size();
Array<float> boundaryLengths;
@@ -3139,7 +3424,7 @@ static bool meshCloseHoles(Mesh *mesh, const Array<uint32_t> &boundaryLoops, con
for (uint32_t i = 0; i < boundaryCount; i++) {
float boundaryLength = 0.0f;
boundaryEdgeCounts[i] = 0;
- for (Mesh::BoundaryEdgeIterator it(mesh, boundaryLoops[i]); !it.isDone(); it.advance()) {
+ for (Mesh::BoundaryLoopEdgeIterator it(mesh, boundaryLoops[i]); !it.isDone(); it.advance()) {
const Vector3 &t0 = mesh->position(mesh->vertexAt(meshEdgeIndex0(it.edge())));
const Vector3 &t1 = mesh->position(mesh->vertexAt(meshEdgeIndex1(it.edge())));
boundaryLength += length(t1 - t0);
@@ -3167,7 +3452,7 @@ static bool meshCloseHoles(Mesh *mesh, const Array<uint32_t> &boundaryLoops, con
holePoints.resize(boundaryEdgeCounts[i]);
// Winding is backwards for internal boundaries.
uint32_t e = 0;
- for (Mesh::BoundaryEdgeIterator it(mesh, boundaryLoops[i]); !it.isDone(); it.advance()) {
+ for (Mesh::BoundaryLoopEdgeIterator it(mesh, boundaryLoops[i]); !it.isDone(); it.advance()) {
const uint32_t vertex = mesh->vertexAt(meshEdgeIndex0(it.edge()));
holeVertices[boundaryEdgeCounts[i] - 1 - e] = vertex;
holePoints[boundaryEdgeCounts[i] - 1 - e] = mesh->position(vertex);
@@ -3176,7 +3461,10 @@ static bool meshCloseHoles(Mesh *mesh, const Array<uint32_t> &boundaryLoops, con
const uint32_t oldFaceCount = mesh->faceCount();
if (!meshCloseHole(mesh, holeVertices, normal))
result = false; // Return false if any hole failed to close, but keep trying to close other holes.
- holeFaceCounts.push_back(mesh->faceCount() - oldFaceCount);
+ if (holeCount)
+ (*holeCount)++;
+ if (holeFaceCounts)
+ holeFaceCounts->push_back(mesh->faceCount() - oldFaceCount);
}
return result;
}
@@ -3307,104 +3595,18 @@ static void meshGetBoundaryLoops(const Mesh &mesh, Array<uint32_t> &boundaryLoop
{
const uint32_t edgeCount = mesh.edgeCount();
BitArray bitFlags(edgeCount);
- bitFlags.clearAll();
+ bitFlags.zeroOutMemory();
boundaryLoops.clear();
// Search for boundary edges. Mark all the edges that belong to the same boundary.
for (uint32_t e = 0; e < edgeCount; e++) {
- if (bitFlags.bitAt(e) || !mesh.isBoundaryEdge(e))
+ if (bitFlags.get(e) || !mesh.isBoundaryEdge(e))
continue;
- for (Mesh::BoundaryEdgeIterator it(&mesh, e); !it.isDone(); it.advance())
- bitFlags.setBitAt(it.edge());
+ for (Mesh::BoundaryLoopEdgeIterator it(&mesh, e); !it.isDone(); it.advance())
+ bitFlags.set(it.edge());
boundaryLoops.push_back(e);
}
}
-class MeshTopology
-{
-public:
- MeshTopology(const Mesh *mesh)
- {
- const uint32_t vertexCount = mesh->colocalVertexCount();
- const uint32_t faceCount = mesh->faceCount();
- const uint32_t edgeCount = mesh->edgeCount();
- Array<uint32_t> stack(MemTag::Default);
- stack.reserve(faceCount);
- BitArray bitFlags(faceCount);
- bitFlags.clearAll();
- // Compute connectivity.
- m_connectedCount = 0;
- for (uint32_t f = 0; f < faceCount; f++ ) {
- if (bitFlags.bitAt(f) == false) {
- m_connectedCount++;
- stack.push_back(f);
- while (!stack.isEmpty()) {
- const uint32_t top = stack.back();
- XA_ASSERT(top != uint32_t(~0));
- stack.pop_back();
- if (bitFlags.bitAt(top) == false) {
- bitFlags.setBitAt(top);
- for (Mesh::FaceEdgeIterator it(mesh, top); !it.isDone(); it.advance()) {
- const uint32_t oppositeFace = it.oppositeFace();
- if (oppositeFace != UINT32_MAX)
- stack.push_back(oppositeFace);
- }
- }
- }
- }
- }
- XA_ASSERT(stack.isEmpty());
- // Count boundary loops.
- m_boundaryCount = 0;
- bitFlags.resize(edgeCount);
- bitFlags.clearAll();
- // Don't forget to link the boundary otherwise this won't work.
- for (uint32_t e = 0; e < edgeCount; e++) {
- if (bitFlags.bitAt(e) || !mesh->isBoundaryEdge(e))
- continue;
- m_boundaryCount++;
- for (Mesh::BoundaryEdgeIterator it(mesh, e); !it.isDone(); it.advance())
- bitFlags.setBitAt(it.edge());
- }
- // Compute euler number.
- m_eulerNumber = vertexCount - edgeCount + faceCount;
- // Compute genus. (only valid on closed connected surfaces)
- m_genus = -1;
- if (isClosed() && isConnected())
- m_genus = (2 - m_eulerNumber) / 2;
- }
-
- /// Determine if the mesh is connected.
- bool isConnected() const
- {
- return m_connectedCount == 1;
- }
-
- /// Determine if the mesh is closed. (Each edge is shared by two faces)
- bool isClosed() const
- {
- return m_boundaryCount == 0;
- }
-
- /// Return true if the mesh has the topology of a disk.
- bool isDisk() const
- {
- return isConnected() && m_boundaryCount == 1/* && m_eulerNumber == 1*/;
- }
-
-private:
- ///< Number of boundary loops.
- int m_boundaryCount;
-
- ///< Number of connected components.
- int m_connectedCount;
-
- ///< Euler number.
- int m_eulerNumber;
-
- /// Mesh genus.
- int m_genus;
-};
-
struct Progress
{
Progress(ProgressCategory::Enum category, ProgressFunc func, void *userData, uint32_t maxValue) : value(0), cancel(false), m_category(category), m_func(func), m_userData(userData), m_maxValue(maxValue), m_progress(0)
@@ -3482,6 +3684,7 @@ class TaskScheduler
public:
TaskScheduler() : m_shutdown(false)
{
+ m_threadIndex = 0;
// Max with current task scheduler usage is 1 per thread + 1 deep nesting, but allow for some slop.
m_maxGroups = std::thread::hardware_concurrency() * 4;
m_groups = XA_ALLOC_ARRAY(MemTag::Default, TaskGroup, m_maxGroups);
@@ -3494,7 +3697,7 @@ public:
for (uint32_t i = 0; i < m_workers.size(); i++) {
new (&m_workers[i]) Worker();
m_workers[i].wakeup = false;
- m_workers[i].thread = XA_NEW_ARGS(MemTag::Default, std::thread, workerThread, this, &m_workers[i]);
+ m_workers[i].thread = XA_NEW_ARGS(MemTag::Default, std::thread, workerThread, this, &m_workers[i], i + 1);
}
}
@@ -3517,6 +3720,11 @@ public:
XA_FREE(m_groups);
}
+ uint32_t threadCount() const
+ {
+ return max(1u, std::thread::hardware_concurrency()); // Including the main thread.
+ }
+
TaskGroupHandle createTaskGroup(uint32_t reserveSize = 0)
{
// Claim the first free group.
@@ -3581,6 +3789,8 @@ public:
handle->value = UINT32_MAX;
}
+ static uint32_t currentThreadIndex() { return m_threadIndex; }
+
private:
struct TaskGroup
{
@@ -3603,9 +3813,11 @@ private:
uint32_t m_maxGroups;
Array<Worker> m_workers;
std::atomic<bool> m_shutdown;
+ static thread_local uint32_t m_threadIndex;
- static void workerThread(TaskScheduler *scheduler, Worker *worker)
+ static void workerThread(TaskScheduler *scheduler, Worker *worker, uint32_t threadIndex)
{
+ m_threadIndex = threadIndex;
std::unique_lock<std::mutex> lock(worker->mutex);
for (;;) {
worker->cv.wait(lock, [=]{ return worker->wakeup.load(); });
@@ -3636,6 +3848,8 @@ private:
}
}
};
+
+thread_local uint32_t TaskScheduler::m_threadIndex;
#else
class TaskScheduler
{
@@ -3646,6 +3860,11 @@ public:
destroyGroup({ i });
}
+ uint32_t threadCount() const
+ {
+ return 1;
+ }
+
TaskGroupHandle createTaskGroup(uint32_t reserveSize = 0)
{
TaskGroup *group = XA_NEW(MemTag::Default, TaskGroup);
@@ -3675,6 +3894,8 @@ public:
handle->value = UINT32_MAX;
}
+ static uint32_t currentThreadIndex() { return 0; }
+
private:
void destroyGroup(TaskGroupHandle handle)
{
@@ -3695,6 +3916,369 @@ private:
};
#endif
+#if XA_DEBUG_EXPORT_TGA
+const uint8_t TGA_TYPE_RGB = 2;
+const uint8_t TGA_ORIGIN_UPPER = 0x20;
+
+#pragma pack(push, 1)
+struct TgaHeader
+{
+ uint8_t id_length;
+ uint8_t colormap_type;
+ uint8_t image_type;
+ uint16_t colormap_index;
+ uint16_t colormap_length;
+ uint8_t colormap_size;
+ uint16_t x_origin;
+ uint16_t y_origin;
+ uint16_t width;
+ uint16_t height;
+ uint8_t pixel_size;
+ uint8_t flags;
+ enum { Size = 18 };
+};
+#pragma pack(pop)
+
+static void WriteTga(const char *filename, const uint8_t *data, uint32_t width, uint32_t height)
+{
+ XA_DEBUG_ASSERT(sizeof(TgaHeader) == TgaHeader::Size);
+ FILE *f;
+ XA_FOPEN(f, filename, "wb");
+ if (!f)
+ return;
+ TgaHeader tga;
+ tga.id_length = 0;
+ tga.colormap_type = 0;
+ tga.image_type = TGA_TYPE_RGB;
+ tga.colormap_index = 0;
+ tga.colormap_length = 0;
+ tga.colormap_size = 0;
+ tga.x_origin = 0;
+ tga.y_origin = 0;
+ tga.width = (uint16_t)width;
+ tga.height = (uint16_t)height;
+ tga.pixel_size = 24;
+ tga.flags = TGA_ORIGIN_UPPER;
+ fwrite(&tga, sizeof(TgaHeader), 1, f);
+ fwrite(data, sizeof(uint8_t), width * height * 3, f);
+ fclose(f);
+}
+#endif
+
+template<typename T>
+class ThreadLocal
+{
+public:
+ ThreadLocal()
+ {
+#if XA_MULTITHREADED
+ const uint32_t n = std::thread::hardware_concurrency();
+#else
+ const uint32_t n = 1;
+#endif
+ m_array = XA_ALLOC_ARRAY(MemTag::Default, T, n);
+ for (uint32_t i = 0; i < n; i++)
+ new (&m_array[i]) T;
+ }
+
+ ~ThreadLocal()
+ {
+#if XA_MULTITHREADED
+ const uint32_t n = std::thread::hardware_concurrency();
+#else
+ const uint32_t n = 1;
+#endif
+ for (uint32_t i = 0; i < n; i++)
+ m_array[i].~T();
+ XA_FREE(m_array);
+ }
+
+ T &get() const
+ {
+ return m_array[TaskScheduler::currentThreadIndex()];
+ }
+
+private:
+ T *m_array;
+};
+
+class UniformGrid2
+{
+public:
+ void reset(const Vector2 *positions, const uint32_t *indices = nullptr, uint32_t reserveEdgeCount = 0)
+ {
+ m_edges.clear();
+ if (reserveEdgeCount > 0)
+ m_edges.reserve(reserveEdgeCount);
+ m_positions = positions;
+ m_indices = indices;
+ m_cellDataOffsets.clear();
+ }
+
+ void append(uint32_t edge)
+ {
+ XA_DEBUG_ASSERT(m_cellDataOffsets.isEmpty());
+ m_edges.push_back(edge);
+ }
+
+ bool intersect(Vector2 v1, Vector2 v2, float epsilon)
+ {
+ const uint32_t edgeCount = m_edges.size();
+ bool bruteForce = edgeCount <= 64;
+ if (!bruteForce && m_cellDataOffsets.isEmpty())
+ bruteForce = !createGrid();
+ if (bruteForce) {
+ for (uint32_t j = 0; j < edgeCount; j++) {
+ const uint32_t edge = m_edges[j];
+ if (linesIntersect(v1, v2, edgePosition0(edge), edgePosition1(edge), epsilon))
+ return true;
+ }
+ } else {
+ computePotentialEdges(v1, v2);
+ uint32_t prevEdge = UINT32_MAX;
+ for (uint32_t j = 0; j < m_potentialEdges.size(); j++) {
+ const uint32_t edge = m_potentialEdges[j];
+ if (edge == prevEdge)
+ continue;
+ if (linesIntersect(v1, v2, edgePosition0(edge), edgePosition1(edge), epsilon))
+ return true;
+ prevEdge = edge;
+ }
+ }
+ return false;
+ }
+
+ bool intersectSelf(float epsilon)
+ {
+ const uint32_t edgeCount = m_edges.size();
+ bool bruteForce = edgeCount <= 64;
+ if (!bruteForce && m_cellDataOffsets.isEmpty())
+ bruteForce = !createGrid();
+ for (uint32_t i = 0; i < edgeCount; i++) {
+ const uint32_t edge1 = m_edges[i];
+ if (bruteForce) {
+ for (uint32_t j = 0; j < edgeCount; j++) {
+ const uint32_t edge2 = m_edges[j];
+ if (edgesIntersect(edge1, edge2, epsilon))
+ return true;
+ }
+ } else {
+ computePotentialEdges(edgePosition0(edge1), edgePosition1(edge1));
+ uint32_t prevEdge = UINT32_MAX;
+ for (uint32_t j = 0; j < m_potentialEdges.size(); j++) {
+ const uint32_t edge2 = m_potentialEdges[j];
+ if (edge2 == prevEdge)
+ continue;
+ if (edgesIntersect(edge1, edge2, epsilon))
+ return true;
+ prevEdge = edge2;
+ }
+ }
+ }
+ return false;
+ }
+
+#if XA_DEBUG_EXPORT_BOUNDARY_GRID
+ void debugExport(const char *filename)
+ {
+ Array<uint8_t> image;
+ image.resize(m_gridWidth * m_gridHeight * 3);
+ for (uint32_t y = 0; y < m_gridHeight; y++) {
+ for (uint32_t x = 0; x < m_gridWidth; x++) {
+ uint8_t *bgr = &image[(x + y * m_gridWidth) * 3];
+ bgr[0] = bgr[1] = bgr[2] = 32;
+ uint32_t offset = m_cellDataOffsets[x + y * m_gridWidth];
+ while (offset != UINT32_MAX) {
+ const uint32_t edge2 = m_cellData[offset];
+ srand(edge2);
+ for (uint32_t i = 0; i < 3; i++)
+ bgr[i] = uint8_t(bgr[i] * 0.5f + (rand() % 255) * 0.5f);
+ offset = m_cellData[offset + 1];
+ }
+ }
+ }
+ WriteTga(filename, image.data(), m_gridWidth, m_gridHeight);
+ }
+#endif
+
+private:
+ bool createGrid()
+ {
+ // Compute edge extents. Min will be the grid origin.
+ const uint32_t edgeCount = m_edges.size();
+ Extents2 edgeExtents;
+ edgeExtents.reset();
+ for (uint32_t i = 0; i < edgeCount; i++) {
+ const uint32_t edge = m_edges[i];
+ edgeExtents.add(edgePosition0(edge));
+ edgeExtents.add(edgePosition1(edge));
+ }
+ m_gridOrigin = edgeExtents.min;
+ // Size grid to approximately one edge per cell.
+ const Vector2 extentsSize(edgeExtents.max - edgeExtents.min);
+ m_cellSize = min(extentsSize.x, extentsSize.y) / sqrtf((float)edgeCount);
+ if (m_cellSize <= 0.0f)
+ return false;
+ m_gridWidth = uint32_t(ceilf(extentsSize.x / m_cellSize));
+ m_gridHeight = uint32_t(ceilf(extentsSize.y / m_cellSize));
+ if (m_gridWidth == 0 || m_gridHeight == 0)
+ return false;
+ // Insert edges into cells.
+ m_cellDataOffsets.resize(m_gridWidth * m_gridHeight);
+ for (uint32_t i = 0; i < m_cellDataOffsets.size(); i++)
+ m_cellDataOffsets[i] = UINT32_MAX;
+ m_cellData.clear();
+ m_cellData.reserve(edgeCount * 2);
+ for (uint32_t i = 0; i < edgeCount; i++) {
+ const uint32_t edge = m_edges[i];
+ traverse(edgePosition0(edge), edgePosition1(edge));
+ XA_DEBUG_ASSERT(!m_traversedCellOffsets.isEmpty());
+ for (uint32_t j = 0; j < m_traversedCellOffsets.size(); j++) {
+ const uint32_t cell = m_traversedCellOffsets[j];
+ uint32_t offset = m_cellDataOffsets[cell];
+ if (offset == UINT32_MAX)
+ m_cellDataOffsets[cell] = m_cellData.size();
+ else {
+ for (;;) {
+ uint32_t &nextOffset = m_cellData[offset + 1];
+ if (nextOffset == UINT32_MAX) {
+ nextOffset = m_cellData.size();
+ break;
+ }
+ offset = nextOffset;
+ }
+ }
+ m_cellData.push_back(edge);
+ m_cellData.push_back(UINT32_MAX);
+ }
+ }
+ return true;
+ }
+
+ void computePotentialEdges(Vector2 p1, Vector2 p2)
+ {
+ m_potentialEdges.clear();
+ traverse(p1, p2);
+ for (uint32_t j = 0; j < m_traversedCellOffsets.size(); j++) {
+ const uint32_t cell = m_traversedCellOffsets[j];
+ uint32_t offset = m_cellDataOffsets[cell];
+ while (offset != UINT32_MAX) {
+ const uint32_t edge2 = m_cellData[offset];
+ m_potentialEdges.push_back(edge2);
+ offset = m_cellData[offset + 1];
+ }
+ }
+ if (m_potentialEdges.isEmpty())
+ return;
+ insertionSort(m_potentialEdges.data(), m_potentialEdges.size());
+ }
+
+ // "A Fast Voxel Traversal Algorithm for Ray Tracing"
+ void traverse(Vector2 p1, Vector2 p2)
+ {
+ const Vector2 dir = p2 - p1;
+ const Vector2 normal = normalizeSafe(dir, Vector2(0.0f), kEpsilon);
+ const int stepX = dir.x >= 0 ? 1 : -1;
+ const int stepY = dir.y >= 0 ? 1 : -1;
+ const uint32_t firstCell[2] = { cellX(p1.x), cellY(p1.y) };
+ const uint32_t lastCell[2] = { cellX(p2.x), cellY(p2.y) };
+ float distToNextCellX;
+ if (stepX == 1)
+ distToNextCellX = (firstCell[0] + 1) * m_cellSize - (p1.x - m_gridOrigin.x);
+ else
+ distToNextCellX = (p1.x - m_gridOrigin.x) - firstCell[0] * m_cellSize;
+ float distToNextCellY;
+ if (stepY == 1)
+ distToNextCellY = (firstCell[1] + 1) * m_cellSize - (p1.y - m_gridOrigin.y);
+ else
+ distToNextCellY = (p1.y - m_gridOrigin.y) - firstCell[1] * m_cellSize;
+ float tMaxX, tMaxY, tDeltaX, tDeltaY;
+ if (normal.x > kEpsilon || normal.x < -kEpsilon) {
+ tMaxX = (distToNextCellX * stepX) / normal.x;
+ tDeltaX = (m_cellSize * stepX) / normal.x;
+ }
+ else
+ tMaxX = tDeltaX = FLT_MAX;
+ if (normal.y > kEpsilon || normal.y < -kEpsilon) {
+ tMaxY = (distToNextCellY * stepY) / normal.y;
+ tDeltaY = (m_cellSize * stepY) / normal.y;
+ }
+ else
+ tMaxY = tDeltaY = FLT_MAX;
+ m_traversedCellOffsets.clear();
+ m_traversedCellOffsets.push_back(firstCell[0] + firstCell[1] * m_gridWidth);
+ uint32_t currentCell[2] = { firstCell[0], firstCell[1] };
+ while (!(currentCell[0] == lastCell[0] && currentCell[1] == lastCell[1])) {
+ if (tMaxX < tMaxY) {
+ tMaxX += tDeltaX;
+ currentCell[0] += stepX;
+ } else {
+ tMaxY += tDeltaY;
+ currentCell[1] += stepY;
+ }
+ if (currentCell[0] >= m_gridWidth || currentCell[1] >= m_gridHeight)
+ break;
+ if (stepX == 0 && currentCell[0] < lastCell[0])
+ break;
+ if (stepX == 1 && currentCell[0] > lastCell[0])
+ break;
+ if (stepY == 0 && currentCell[1] < lastCell[1])
+ break;
+ if (stepY == 1 && currentCell[1] > lastCell[1])
+ break;
+ m_traversedCellOffsets.push_back(currentCell[0] + currentCell[1] * m_gridWidth);
+ }
+ }
+
+ bool edgesIntersect(uint32_t edge1, uint32_t edge2, float epsilon) const
+ {
+ if (edge1 == edge2)
+ return false;
+ const uint32_t ai[2] = { vertexAt(meshEdgeIndex0(edge1)), vertexAt(meshEdgeIndex1(edge1)) };
+ const uint32_t bi[2] = { vertexAt(meshEdgeIndex0(edge2)), vertexAt(meshEdgeIndex1(edge2)) };
+ // Ignore connected edges, since they can't intersect (only overlap), and may be detected as false positives.
+ if (ai[0] == bi[0] || ai[0] == bi[1] || ai[1] == bi[0] || ai[1] == bi[1])
+ return false;
+ return linesIntersect(m_positions[ai[0]], m_positions[ai[1]], m_positions[bi[0]], m_positions[bi[1]], epsilon);
+ }
+
+ uint32_t cellX(float x) const
+ {
+ return min((uint32_t)max(0.0f, (x - m_gridOrigin.x) / m_cellSize), m_gridWidth - 1u);
+ }
+
+ uint32_t cellY(float y) const
+ {
+ return min((uint32_t)max(0.0f, (y - m_gridOrigin.y) / m_cellSize), m_gridHeight - 1u);
+ }
+
+ Vector2 edgePosition0(uint32_t edge) const
+ {
+ return m_positions[vertexAt(meshEdgeIndex0(edge))];
+ }
+
+ Vector2 edgePosition1(uint32_t edge) const
+ {
+ return m_positions[vertexAt(meshEdgeIndex1(edge))];
+ }
+
+ uint32_t vertexAt(uint32_t index) const
+ {
+ return m_indices ? m_indices[index] : index;
+ }
+
+ Array<uint32_t> m_edges;
+ const Vector2 *m_positions;
+ const uint32_t *m_indices; // Optional
+ float m_cellSize;
+ Vector2 m_gridOrigin;
+ uint32_t m_gridWidth, m_gridHeight; // in cells
+ Array<uint32_t> m_cellDataOffsets;
+ Array<uint32_t> m_cellData;
+ Array<uint32_t> m_potentialEdges;
+ Array<uint32_t> m_traversedCellOffsets;
+};
+
struct UvMeshChart
{
Array<uint32_t> faces;
@@ -3834,15 +4418,16 @@ struct Triangle
// make sure every triangle is front facing.
flipBackface();
// Compute deltas.
- computeUnitInwardNormals();
+ if (isValid())
+ computeUnitInwardNormals();
}
bool isValid()
{
const Vector2 e0 = v3 - v1;
const Vector2 e1 = v2 - v1;
- const float denom = 1.0f / (e0.y * e1.x - e1.y * e0.x);
- return isFinite(denom);
+ const float area = e0.y * e1.x - e1.y * e0.x;
+ return area != 0.0f;
}
// extents has to be multiple of BK_SIZE!!
@@ -3926,6 +4511,7 @@ struct Triangle
return true;
}
+private:
void flipBackface()
{
// check if triangle is backfacing, if so, swap two vertices
@@ -3941,13 +4527,13 @@ struct Triangle
{
n1 = v1 - v2;
n1 = Vector2(-n1.y, n1.x);
- n1 = n1 * (1.0f / sqrtf(n1.x * n1.x + n1.y * n1.y));
+ n1 = n1 * (1.0f / sqrtf(dot(n1, n1)));
n2 = v2 - v3;
n2 = Vector2(-n2.y, n2.x);
- n2 = n2 * (1.0f / sqrtf(n2.x * n2.x + n2.y * n2.y));
+ n2 = n2 * (1.0f / sqrtf(dot(n2, n2)));
n3 = v3 - v1;
n3 = Vector2(-n3.y, n3.x);
- n3 = n3 * (1.0f / sqrtf(n3.x * n3.x + n3.y * n3.y));
+ n3 = n3 * (1.0f / sqrtf(dot(n3, n3)));
}
// Vertices.
@@ -3990,28 +4576,33 @@ public:
float v; // value
};
- Matrix(uint32_t d) : m_width(d)
+ Matrix(uint32_t d) : m_width(d), m_array(MemTag::Matrix)
{
m_array.resize(d);
- for (uint32_t i = 0; i < m_array.size(); i++)
- new (&m_array[i]) Array<Coefficient>();
+ m_array.runCtors();
+#if XA_DEBUG_HEAP
+ for (uint32_t i = 0; i < d; i++)
+ m_array[i].setMemTag(MemTag::Matrix);
+#endif
}
- Matrix(uint32_t w, uint32_t h) : m_width(w)
+ Matrix(uint32_t w, uint32_t h) : m_width(w), m_array(MemTag::Matrix)
{
m_array.resize(h);
- for (uint32_t i = 0; i < m_array.size(); i++)
- new (&m_array[i]) Array<Coefficient>();
+ m_array.runCtors();
+#if XA_DEBUG_HEAP
+ for (uint32_t i = 0; i < h; i++)
+ m_array[i].setMemTag(MemTag::Matrix);
+#endif
}
~Matrix()
{
- for (uint32_t i = 0; i < m_array.size(); i++)
- m_array[i].~Array();
+ m_array.runDtors();
}
Matrix(const Matrix &m) = delete;
- const Matrix &operator=(const Matrix &m) = delete;
+ Matrix &operator=(const Matrix &m) = delete;
uint32_t width() const { return m_width; }
uint32_t height() const { return m_array.size(); }
bool isSquare() const { return width() == height(); }
@@ -4211,164 +4802,164 @@ static void mult(const Matrix &A, const Matrix &B, Matrix &C)
namespace segment {
-// Dummy implementation of a priority queue using sort at insertion.
// - Insertion is o(n)
// - Smallest element goes at the end, so that popping it is o(1).
-// - Resorting is n*log(n)
-// @@ Number of elements in the queue is usually small, and we'd have to rebalance often. I'm not sure it's worth implementing a heap.
-// @@ Searcing at removal would remove the need for sorting when priorities change.
-struct PriorityQueue
+struct CostQueue
{
- PriorityQueue(uint32_t size = UINT32_MAX) : maxSize(size) {}
+ CostQueue(uint32_t size = UINT32_MAX) : m_maxSize(size), m_pairs(MemTag::SegmentAtlasChartCandidates) {}
- void push(float priority, uint32_t face)
+ float peekCost() const
{
- uint32_t i = 0;
- const uint32_t count = pairs.size();
- for (; i < count; i++) {
- if (pairs[i].priority > priority) break;
- }
- Pair p = { priority, face };
- pairs.insertAt(i, p);
- if (pairs.size() > maxSize)
- pairs.removeAt(0);
+ return m_pairs.back().cost;
}
- // push face out of order, to be sorted later.
- void push(uint32_t face)
+ uint32_t peekFace() const
{
- Pair p = { 0.0f, face };
- pairs.push_back(p);
+ return m_pairs.back().face;
}
- uint32_t pop()
+ void push(float cost, uint32_t face)
{
- XA_DEBUG_ASSERT(!pairs.isEmpty());
- uint32_t f = pairs.back().face;
- pairs.pop_back();
- return f;
+ const Pair p = { cost, face };
+ if (m_pairs.isEmpty() || cost < peekCost())
+ m_pairs.push_back(p);
+ else {
+ uint32_t i = 0;
+ const uint32_t count = m_pairs.size();
+ for (; i < count; i++) {
+ if (m_pairs[i].cost < cost)
+ break;
+ }
+ m_pairs.insertAt(i, p);
+ if (m_pairs.size() > m_maxSize)
+ m_pairs.removeAt(0);
+ }
}
- void sort()
+ uint32_t pop()
{
- //sort(pairs); // @@ My intro sort appears to be much slower than it should!
- std::sort(pairs.begin(), pairs.end());
+ XA_DEBUG_ASSERT(!m_pairs.isEmpty());
+ uint32_t f = m_pairs.back().face;
+ m_pairs.pop_back();
+ return f;
}
XA_INLINE void clear()
{
- pairs.clear();
+ m_pairs.clear();
}
XA_INLINE uint32_t count() const
{
- return pairs.size();
+ return m_pairs.size();
}
- float firstPriority() const
- {
- return pairs.back().priority;
- }
-
- const uint32_t maxSize;
+private:
+ const uint32_t m_maxSize;
struct Pair
{
- bool operator<(const Pair &p) const
- {
- return priority > p.priority; // !! Sort in inverse priority order!
- }
-
- float priority;
+ float cost;
uint32_t face;
};
- Array<Pair> pairs;
+ Array<Pair> m_pairs;
};
struct Chart
{
+ Chart() : faces(MemTag::SegmentAtlasChartFaces) {}
+
int id = -1;
- Vector3 averageNormal = Vector3(0.0f);
+ Basis basis; // Best fit normal.
float area = 0.0f;
float boundaryLength = 0.0f;
- Vector3 normalSum = Vector3(0.0f);
Vector3 centroidSum = Vector3(0.0f); // Sum of chart face centroids.
Vector3 centroid = Vector3(0.0f); // Average centroid of chart faces.
Array<uint32_t> seeds;
Array<uint32_t> faces;
- PriorityQueue candidates;
- Basis basis; // Of first face.
+ Array<uint32_t> failedPlanarRegions;
+ CostQueue candidates;
};
struct Atlas
{
- // @@ Hardcoded to 10?
- Atlas(const Mesh *mesh, Array<uint32_t> *meshFaces, const ChartOptions &options) : m_mesh(mesh), m_meshFaces(meshFaces), m_facesLeft(mesh->faceCount()), m_bestTriangles(10), m_options(options)
+ Atlas() : m_edgeLengths(MemTag::SegmentAtlasMeshData), m_faceAreas(MemTag::SegmentAtlasMeshData), m_faceNormals(MemTag::SegmentAtlasMeshData), m_texcoords(MemTag::SegmentAtlasMeshData), m_bestTriangles(10), m_nextPlanarRegionFace(MemTag::SegmentAtlasPlanarRegions), m_facePlanarRegionId(MemTag::SegmentAtlasPlanarRegions) {}
+
+ ~Atlas()
+ {
+ const uint32_t chartCount = m_charts.size();
+ for (uint32_t i = 0; i < chartCount; i++) {
+ m_charts[i]->~Chart();
+ XA_FREE(m_charts[i]);
+ }
+ }
+
+ uint32_t facesLeft() const { return m_facesLeft; }
+ uint32_t chartCount() const { return m_charts.size(); }
+ const Array<uint32_t> &chartFaces(uint32_t i) const { return m_charts[i]->faces; }
+ const Basis &chartBasis(uint32_t chartIndex) const { return m_charts[chartIndex]->basis; }
+
+ void reset(uint32_t meshId, uint32_t chartGroupId, const Mesh *mesh, const ChartOptions &options)
{
+ XA_UNUSED(meshId);
+ XA_UNUSED(chartGroupId);
XA_PROFILE_START(buildAtlasInit)
+ m_mesh = mesh;
const uint32_t faceCount = m_mesh->faceCount();
- if (meshFaces) {
- m_ignoreFaces.resize(faceCount);
- m_ignoreFaces.setAll(true);
- for (uint32_t f = 0; f < meshFaces->size(); f++)
- m_ignoreFaces[(*meshFaces)[f]] = false;
- m_facesLeft = meshFaces->size();
- } else {
- m_ignoreFaces.resize(faceCount);
- m_ignoreFaces.setAll(false);
+ m_facesLeft = faceCount;
+ m_options = options;
+ m_rand.reset();
+ const uint32_t chartCount = m_charts.size();
+ for (uint32_t i = 0; i < chartCount; i++) {
+ m_charts[i]->~Chart();
+ XA_FREE(m_charts[i]);
}
- m_faceChartArray.resize(faceCount);
- m_faceChartArray.setAll(-1);
- m_faceCandidateCharts.resize(faceCount);
- m_faceCandidateCosts.resize(faceCount);
+ m_charts.clear();
+ m_faceCharts.resize(faceCount);
+ m_faceCharts.setAll(-1);
m_texcoords.resize(faceCount * 3);
- // @@ Floyd for the whole mesh is too slow. We could compute floyd progressively per patch as the patch grows. We need a better solution to compute most central faces.
- //computeShortestPaths();
// Precompute edge lengths and face areas.
const uint32_t edgeCount = m_mesh->edgeCount();
m_edgeLengths.resize(edgeCount);
- m_edgeLengths.zeroOutMemory();
m_faceAreas.resize(faceCount);
- m_faceAreas.zeroOutMemory();
m_faceNormals.resize(faceCount);
- m_faceTangents.resize(faceCount);
- m_faceBitangents.resize(faceCount);
for (uint32_t f = 0; f < faceCount; f++) {
- if (m_ignoreFaces[f])
- continue;
- for (Mesh::FaceEdgeIterator it(m_mesh, f); !it.isDone(); it.advance()) {
- m_edgeLengths[it.edge()] = internal::length(it.position1() - it.position0());
- XA_DEBUG_ASSERT(m_edgeLengths[it.edge()] > 0.0f);
+ for (uint32_t i = 0; i < 3; i++) {
+ const uint32_t edge = f * 3 + i;
+ const Vector3 &p0 = mesh->position(m_mesh->vertexAt(meshEdgeIndex0(edge)));
+ const Vector3 &p1 = mesh->position(m_mesh->vertexAt(meshEdgeIndex1(edge)));
+ m_edgeLengths[edge] = length(p1 - p0);
+ XA_DEBUG_ASSERT(m_edgeLengths[edge] > 0.0f);
}
- m_faceAreas[f] = mesh->faceArea(f);
+ m_faceAreas[f] = m_mesh->computeFaceArea(f);
XA_DEBUG_ASSERT(m_faceAreas[f] > 0.0f);
- m_faceNormals[f] = m_mesh->triangleNormal(f);
- m_faceTangents[f] = Basis::computeTangent(m_faceNormals[f]);
- m_faceBitangents[f] = Basis::computeBitangent(m_faceNormals[f], m_faceTangents[f]);
+ m_faceNormals[f] = m_mesh->computeFaceNormal(f);
}
-#if XA_GROW_CHARTS_COPLANAR
// Precompute regions of coplanar incident faces.
m_nextPlanarRegionFace.resize(faceCount);
- for (uint32_t f = 0; f < faceCount; f++)
+ m_facePlanarRegionId.resize(faceCount);
+ for (uint32_t f = 0; f < faceCount; f++) {
m_nextPlanarRegionFace[f] = f;
+ m_facePlanarRegionId[f] = UINT32_MAX;
+ }
Array<uint32_t> faceStack;
faceStack.reserve(min(faceCount, 16u));
+ uint32_t planarRegionCount = 0;
for (uint32_t f = 0; f < faceCount; f++) {
if (m_nextPlanarRegionFace[f] != f)
continue; // Already assigned.
- if (m_ignoreFaces[f])
- continue;
faceStack.clear();
faceStack.push_back(f);
for (;;) {
if (faceStack.isEmpty())
break;
const uint32_t face = faceStack.back();
+ m_facePlanarRegionId[face] = planarRegionCount;
faceStack.pop_back();
for (Mesh::FaceEdgeIterator it(m_mesh, face); !it.isDone(); it.advance()) {
const uint32_t oface = it.oppositeFace();
- if (it.isBoundary() || m_ignoreFaces[oface])
+ if (it.isBoundary())
continue;
if (m_nextPlanarRegionFace[oface] != oface)
continue; // Already assigned.
@@ -4377,29 +4968,33 @@ struct Atlas
const uint32_t next = m_nextPlanarRegionFace[face];
m_nextPlanarRegionFace[face] = oface;
m_nextPlanarRegionFace[oface] = next;
+ m_facePlanarRegionId[oface] = planarRegionCount;
faceStack.push_back(oface);
}
}
+ planarRegionCount++;
+ }
+#if XA_DEBUG_EXPORT_OBJ_PLANAR_REGIONS
+ char filename[256];
+ XA_SPRINTF(filename, sizeof(filename), "debug_mesh_%03u_chartgroup_%03u_planar_regions.obj", meshId, chartGroupId);
+ FILE *file;
+ XA_FOPEN(file, filename, "w");
+ if (file) {
+ m_mesh->writeObjVertices(file);
+ fprintf(file, "s off\n");
+ for (uint32_t i = 0; i < planarRegionCount; i++) {
+ fprintf(file, "o region%u\n", i);
+ for (uint32_t j = 0; j < faceCount; j++) {
+ if (m_facePlanarRegionId[j] == i)
+ m_mesh->writeObjFace(file, j);
+ }
+ }
+ fclose(file);
}
#endif
XA_PROFILE_END(buildAtlasInit)
}
- ~Atlas()
- {
- const uint32_t chartCount = m_chartArray.size();
- for (uint32_t i = 0; i < chartCount; i++) {
- m_chartArray[i]->~Chart();
- XA_FREE(m_chartArray[i]);
- }
- }
-
- uint32_t facesLeft() const { return m_facesLeft; }
- uint32_t chartCount() const { return m_chartArray.size(); }
- const Array<uint32_t> &chartFaces(uint32_t i) const { return m_chartArray[i]->faces; }
- const Basis &chartBasis(uint32_t chartIndex) const { return m_chartArray[chartIndex]->basis; }
- const Vector2 *faceTexcoords(uint32_t face) const { return &m_texcoords[face * 3]; }
-
void placeSeeds(float threshold)
{
XA_PROFILE_START(buildAtlasPlaceSeeds)
@@ -4415,28 +5010,51 @@ struct Atlas
}
// Returns true if any of the charts can grow more.
- bool growCharts(float threshold)
+ void growCharts(float threshold)
{
XA_PROFILE_START(buildAtlasGrowCharts)
- // Build global candidate list.
- m_faceCandidateCharts.zeroOutMemory();
- for (uint32_t i = 0; i < m_chartArray.size(); i++)
- addChartCandidateToGlobalCandidates(m_chartArray[i]);
- // Add one candidate face per chart (threshold permitting).
- const uint32_t faceCount = m_mesh->faceCount();
- bool canAddAny = false;
- for (uint32_t f = 0; f < faceCount; f++) {
- Chart *chart = m_faceCandidateCharts[f];
- if (!chart || m_faceCandidateCosts[f] > threshold)
- continue;
- createFaceTexcoords(chart, f);
- if (!canAddFaceToChart(chart, f))
- continue;
- addFaceToChart(chart, f);
- canAddAny = true;
+ for (;;) {
+ if (m_facesLeft == 0)
+ break;
+ // Get the single best candidate out of the chart best candidates.
+ uint32_t bestFace = UINT32_MAX, bestChart = UINT32_MAX;
+ float lowestCost = FLT_MAX;
+ for (uint32_t i = 0; i < m_charts.size(); i++) {
+ Chart *chart = m_charts[i];
+ // Get the best candidate from the chart.
+ // Cleanup any best candidates that have been claimed by another chart.
+ uint32_t face = UINT32_MAX;
+ float cost = FLT_MAX;
+ for (;;) {
+ if (chart->candidates.count() == 0)
+ break;
+ cost = chart->candidates.peekCost();
+ face = chart->candidates.peekFace();
+ if (m_faceCharts[face] == -1)
+ break;
+ else {
+ // Face belongs to another chart. Pop from queue so the next best candidate can be retrieved.
+ chart->candidates.pop();
+ face = UINT32_MAX;
+ }
+ }
+ if (face == UINT32_MAX)
+ continue; // No candidates for this chart.
+ // See if best candidate overall.
+ if (cost < lowestCost) {
+ lowestCost = cost;
+ bestFace = face;
+ bestChart = i;
+ }
+ }
+ if (bestFace == UINT32_MAX || lowestCost > threshold)
+ break;
+ Chart *chart = m_charts[bestChart];
+ chart->candidates.pop(); // Pop the selected candidate from the queue.
+ if (!addFaceToChart(chart, bestFace))
+ chart->failedPlanarRegions.push_back(m_facePlanarRegionId[bestFace]);
}
XA_PROFILE_END(buildAtlasGrowCharts)
- return canAddAny && m_facesLeft != 0; // Can continue growing.
}
void resetCharts()
@@ -4444,53 +5062,34 @@ struct Atlas
XA_PROFILE_START(buildAtlasResetCharts)
const uint32_t faceCount = m_mesh->faceCount();
for (uint32_t i = 0; i < faceCount; i++)
- m_faceChartArray[i] = -1;
- m_facesLeft = m_meshFaces ? m_meshFaces->size() : faceCount;
- const uint32_t chartCount = m_chartArray.size();
+ m_faceCharts[i] = -1;
+ m_facesLeft = faceCount;
+ const uint32_t chartCount = m_charts.size();
for (uint32_t i = 0; i < chartCount; i++) {
- Chart *chart = m_chartArray[i];
+ Chart *chart = m_charts[i];
const uint32_t seed = chart->seeds.back();
chart->area = 0.0f;
chart->boundaryLength = 0.0f;
- chart->normalSum = Vector3(0.0f);
+ chart->basis.normal = Vector3(0.0f);
+ chart->basis.tangent = Vector3(0.0f);
+ chart->basis.bitangent = Vector3(0.0f);
chart->centroidSum = Vector3(0.0f);
chart->centroid = Vector3(0.0f);
chart->faces.clear();
chart->candidates.clear();
+ chart->failedPlanarRegions.clear();
addFaceToChart(chart, seed);
}
-#if XA_GROW_CHARTS_COPLANAR
- for (uint32_t i = 0; i < chartCount; i++) {
- Chart *chart = m_chartArray[i];
- growChartCoplanar(chart);
- }
-#endif
XA_PROFILE_END(buildAtlasResetCharts)
}
- void updateChartCandidates(Chart *chart, uint32_t f)
- {
- // Traverse neighboring faces, add the ones that do not belong to any chart yet.
- for (Mesh::FaceEdgeIterator it(m_mesh, f); !it.isDone(); it.advance()) {
- if (!it.isBoundary() && !m_ignoreFaces[it.oppositeFace()] && m_faceChartArray[it.oppositeFace()] == -1)
- chart->candidates.push(it.oppositeFace());
- }
- // Re-evaluate all candidate priorities.
- uint32_t candidateCount = chart->candidates.count();
- for (uint32_t i = 0; i < candidateCount; i++) {
- PriorityQueue::Pair &pair = chart->candidates.pairs[i];
- pair.priority = evaluateCost(chart, pair.face);
- }
- chart->candidates.sort();
- }
-
bool relocateSeeds()
{
XA_PROFILE_START(buildAtlasRelocateSeeds)
bool anySeedChanged = false;
- const uint32_t chartCount = m_chartArray.size();
+ const uint32_t chartCount = m_charts.size();
for (uint32_t i = 0; i < chartCount; i++) {
- if (relocateSeed(m_chartArray[i])) {
+ if (relocateSeed(m_charts[i])) {
anySeedChanged = true;
}
}
@@ -4510,45 +5109,38 @@ struct Atlas
void mergeCharts()
{
XA_PROFILE_START(buildAtlasMergeCharts)
- Array<float> sharedBoundaryLengths;
- Array<float> sharedBoundaryLengthsNoSeams;
- Array<uint32_t> sharedBoundaryEdgeCountNoSeams;
- Array<Vector2> tempTexcoords;
- const uint32_t chartCount = m_chartArray.size();
+ const uint32_t chartCount = m_charts.size();
// Merge charts progressively until there's none left to merge.
for (;;) {
bool merged = false;
for (int c = chartCount - 1; c >= 0; c--) {
- Chart *chart = m_chartArray[c];
+ Chart *chart = m_charts[c];
if (chart == nullptr)
continue;
float externalBoundaryLength = 0.0f;
- sharedBoundaryLengths.clear();
- sharedBoundaryLengths.resize(chartCount);
- sharedBoundaryLengths.zeroOutMemory();
- sharedBoundaryLengthsNoSeams.clear();
- sharedBoundaryLengthsNoSeams.resize(chartCount);
- sharedBoundaryLengthsNoSeams.zeroOutMemory();
- sharedBoundaryEdgeCountNoSeams.clear();
- sharedBoundaryEdgeCountNoSeams.resize(chartCount);
- sharedBoundaryEdgeCountNoSeams.zeroOutMemory();
+ m_sharedBoundaryLengths.resize(chartCount);
+ m_sharedBoundaryLengths.zeroOutMemory();
+ m_sharedBoundaryLengthsNoSeams.resize(chartCount);
+ m_sharedBoundaryLengthsNoSeams.zeroOutMemory();
+ m_sharedBoundaryEdgeCountNoSeams.resize(chartCount);
+ m_sharedBoundaryEdgeCountNoSeams.zeroOutMemory();
const uint32_t faceCount = chart->faces.size();
for (uint32_t i = 0; i < faceCount; i++) {
const uint32_t f = chart->faces[i];
for (Mesh::FaceEdgeIterator it(m_mesh, f); !it.isDone(); it.advance()) {
const float l = m_edgeLengths[it.edge()];
- if (it.isBoundary() || m_ignoreFaces[it.oppositeFace()]) {
+ if (it.isBoundary()) {
externalBoundaryLength += l;
} else {
- const int neighborChart = m_faceChartArray[it.oppositeFace()];
- if (m_chartArray[neighborChart] != chart) {
+ const int neighborChart = m_faceCharts[it.oppositeFace()];
+ if (m_charts[neighborChart] != chart) {
if ((it.isSeam() && (isNormalSeam(it.edge()) || it.isTextureSeam()))) {
externalBoundaryLength += l;
} else {
- sharedBoundaryLengths[neighborChart] += l;
+ m_sharedBoundaryLengths[neighborChart] += l;
}
- sharedBoundaryLengthsNoSeams[neighborChart] += l;
- sharedBoundaryEdgeCountNoSeams[neighborChart]++;
+ m_sharedBoundaryLengthsNoSeams[neighborChart] += l;
+ m_sharedBoundaryEdgeCountNoSeams[neighborChart]++;
}
}
}
@@ -4556,50 +5148,38 @@ struct Atlas
for (int cc = chartCount - 1; cc >= 0; cc--) {
if (cc == c)
continue;
- Chart *chart2 = m_chartArray[cc];
+ Chart *chart2 = m_charts[cc];
if (chart2 == nullptr)
continue;
+ // Must share a boundary.
+ if (m_sharedBoundaryLengths[cc] <= 0.0f)
+ continue;
// Compare proxies.
- if (dot(chart2->averageNormal, chart->averageNormal) < XA_MERGE_CHARTS_MIN_NORMAL_DEVIATION)
+ if (dot(chart2->basis.normal, chart->basis.normal) < XA_MERGE_CHARTS_MIN_NORMAL_DEVIATION)
continue;
// Obey max chart area and boundary length.
if (m_options.maxChartArea > 0.0f && chart->area + chart2->area > m_options.maxChartArea)
continue;
- if (m_options.maxBoundaryLength > 0.0f && chart->boundaryLength + chart2->boundaryLength - sharedBoundaryLengthsNoSeams[cc] > m_options.maxBoundaryLength)
+ if (m_options.maxBoundaryLength > 0.0f && chart->boundaryLength + chart2->boundaryLength - m_sharedBoundaryLengthsNoSeams[cc] > m_options.maxBoundaryLength)
continue;
// Merge if chart2 has a single face.
// chart1 must have more than 1 face.
// chart2 area must be <= 10% of chart1 area.
- if (sharedBoundaryLengthsNoSeams[cc] > 0.0f && chart->faces.size() > 1 && chart2->faces.size() == 1 && chart2->area <= chart->area * 0.1f)
+ if (m_sharedBoundaryLengthsNoSeams[cc] > 0.0f && chart->faces.size() > 1 && chart2->faces.size() == 1 && chart2->area <= chart->area * 0.1f)
goto merge;
// Merge if chart2 has two faces (probably a quad), and chart1 bounds at least 2 of its edges.
- if (chart2->faces.size() == 2 && sharedBoundaryEdgeCountNoSeams[cc] >= 2)
+ if (chart2->faces.size() == 2 && m_sharedBoundaryEdgeCountNoSeams[cc] >= 2)
goto merge;
// Merge if chart2 is wholely inside chart1, ignoring seams.
- if (sharedBoundaryLengthsNoSeams[cc] > 0.0f && equal(sharedBoundaryLengthsNoSeams[cc], chart2->boundaryLength, kEpsilon))
+ if (m_sharedBoundaryLengthsNoSeams[cc] > 0.0f && equal(m_sharedBoundaryLengthsNoSeams[cc], chart2->boundaryLength, kEpsilon))
goto merge;
- if (sharedBoundaryLengths[cc] > 0.2f * max(0.0f, chart->boundaryLength - externalBoundaryLength) ||
- sharedBoundaryLengths[cc] > 0.75f * chart2->boundaryLength)
+ if (m_sharedBoundaryLengths[cc] > 0.2f * max(0.0f, chart->boundaryLength - externalBoundaryLength) ||
+ m_sharedBoundaryLengths[cc] > 0.75f * chart2->boundaryLength)
goto merge;
continue;
merge:
- // Create texcoords for chart 2 using chart 1 basis. Backup chart 2 texcoords for restoration if charts cannot be merged.
- tempTexcoords.resize(chart2->faces.size() * 3);
- for (uint32_t i = 0; i < chart2->faces.size(); i++) {
- const uint32_t face = chart2->faces[i];
- for (uint32_t j = 0; j < 3; j++)
- tempTexcoords[i * 3 + j] = m_texcoords[face * 3 + j];
- createFaceTexcoords(chart, face);
- }
- if (!canMergeCharts(chart, chart2)) {
- // Restore chart 2 texcoords.
- for (uint32_t i = 0; i < chart2->faces.size(); i++) {
- for (uint32_t j = 0; j < 3; j++)
- m_texcoords[chart2->faces[i] * 3 + j] = tempTexcoords[i * 3 + j];
- }
+ if (!mergeChart(chart, chart2, m_sharedBoundaryLengthsNoSeams[cc]))
continue;
- }
- mergeChart(chart, chart2, sharedBoundaryLengthsNoSeams[cc]);
merged = true;
break;
}
@@ -4610,20 +5190,20 @@ struct Atlas
break;
}
// Remove deleted charts.
- for (int c = 0; c < int32_t(m_chartArray.size()); /*do not increment if removed*/) {
- if (m_chartArray[c] == nullptr) {
- m_chartArray.removeAt(c);
- // Update m_faceChartArray.
- const uint32_t faceCount = m_faceChartArray.size();
+ for (int c = 0; c < int32_t(m_charts.size()); /*do not increment if removed*/) {
+ if (m_charts[c] == nullptr) {
+ m_charts.removeAt(c);
+ // Update m_faceCharts.
+ const uint32_t faceCount = m_faceCharts.size();
for (uint32_t i = 0; i < faceCount; i++) {
- XA_DEBUG_ASSERT(m_faceChartArray[i] != c);
- XA_DEBUG_ASSERT(m_faceChartArray[i] <= int32_t(m_chartArray.size()));
- if (m_faceChartArray[i] > c) {
- m_faceChartArray[i]--;
+ XA_DEBUG_ASSERT(m_faceCharts[i] != c);
+ XA_DEBUG_ASSERT(m_faceCharts[i] <= int32_t(m_charts.size()));
+ if (m_faceCharts[i] > c) {
+ m_faceCharts[i]--;
}
}
} else {
- m_chartArray[c]->id = c;
+ m_charts[c]->id = c;
c++;
}
}
@@ -4635,264 +5215,204 @@ private:
void createRandomChart(float threshold)
{
Chart *chart = XA_NEW(MemTag::Default, Chart);
- chart->id = (int)m_chartArray.size();
- m_chartArray.push_back(chart);
+ chart->id = (int)m_charts.size();
+ m_charts.push_back(chart);
// Pick random face that is not used by any chart yet.
uint32_t face = m_rand.getRange(m_mesh->faceCount() - 1);
- while (m_ignoreFaces[face] || m_faceChartArray[face] != -1) {
+ while (m_faceCharts[face] != -1) {
if (++face >= m_mesh->faceCount())
face = 0;
}
chart->seeds.push_back(face);
addFaceToChart(chart, face);
-#if XA_GROW_CHARTS_COPLANAR
- growChartCoplanar(chart);
-#endif
// Grow the chart as much as possible within the given threshold.
- for (uint32_t i = 0; i < m_facesLeft; ) {
- if (chart->candidates.count() == 0 || chart->candidates.firstPriority() > threshold)
+ for (;;) {
+ if (chart->candidates.count() == 0 || chart->candidates.peekCost() > threshold)
break;
const uint32_t f = chart->candidates.pop();
- if (m_faceChartArray[f] != -1)
+ if (m_faceCharts[f] != -1)
continue;
- createFaceTexcoords(chart, f);
- if (!canAddFaceToChart(chart, f))
+ if (!addFaceToChart(chart, f)) {
+ chart->failedPlanarRegions.push_back(m_facePlanarRegionId[f]);
continue;
- addFaceToChart(chart, f);
- i++;
- }
- }
-
- void addChartCandidateToGlobalCandidates(Chart *chart)
- {
- if (chart->candidates.count() == 0)
- return;
- const float cost = chart->candidates.firstPriority();
- const uint32_t face = chart->candidates.pop();
- if (m_faceChartArray[face] != -1) {
- addChartCandidateToGlobalCandidates(chart);
- } else if (!m_faceCandidateCharts[face]) {
- // No candidate assigned to this face yet.
- m_faceCandidateCharts[face] = chart;
- m_faceCandidateCosts[face] = cost;
- } else {
- if (cost < m_faceCandidateCosts[face]) {
- // This is a better candidate for this face (lower cost). The other chart can choose another candidate.
- Chart *otherChart = m_faceCandidateCharts[face];
- m_faceCandidateCharts[face] = chart;
- m_faceCandidateCosts[face] = cost;
- addChartCandidateToGlobalCandidates(otherChart);
- } else {
- // Existing candidate is better. This chart can choose another candidate.
- addChartCandidateToGlobalCandidates(chart);
}
}
}
- void createFaceTexcoords(Chart *chart, uint32_t face)
- {
- for (uint32_t i = 0; i < 3; i++) {
- const Vector3 &pos = m_mesh->position(m_mesh->vertexAt(face * 3 + i));
- m_texcoords[face * 3 + i] = Vector2(dot(chart->basis.tangent, pos), dot(chart->basis.bitangent, pos));
- }
- }
-
bool isChartBoundaryEdge(const Chart *chart, uint32_t edge) const
{
const uint32_t oppositeEdge = m_mesh->oppositeEdge(edge);
const uint32_t oppositeFace = meshEdgeFace(oppositeEdge);
- return oppositeEdge == UINT32_MAX || m_ignoreFaces[oppositeFace] || m_faceChartArray[oppositeFace] != chart->id;
+ return oppositeEdge == UINT32_MAX || m_faceCharts[oppositeFace] != chart->id;
}
- bool edgeArraysIntersect(const uint32_t *edges1, uint32_t edges1Count, const uint32_t *edges2, uint32_t edges2Count)
+ bool computeChartBasis(Chart *chart, Basis *basis)
{
- for (uint32_t i = 0; i < edges1Count; i++) {
- const uint32_t edge1 = edges1[i];
- for (uint32_t j = 0; j < edges2Count; j++) {
- const uint32_t edge2 = edges2[j];
- const Vector2 &a1 = m_texcoords[meshEdgeIndex0(edge1)];
- const Vector2 &a2 = m_texcoords[meshEdgeIndex1(edge1)];
- const Vector2 &b1 = m_texcoords[meshEdgeIndex0(edge2)];
- const Vector2 &b2 = m_texcoords[meshEdgeIndex1(edge2)];
- if (linesIntersect(a1, a2, b1, b2, m_mesh->epsilon()))
- return true;
- }
+ const uint32_t faceCount = chart->faces.size();
+ m_tempPoints.resize(chart->faces.size() * 3);
+ for (uint32_t i = 0; i < faceCount; i++) {
+ const uint32_t f = chart->faces[i];
+ for (uint32_t j = 0; j < 3; j++)
+ m_tempPoints[i * 3 + j] = m_mesh->position(m_mesh->vertexAt(f * 3 + j));
}
- return false;
+ return Fit::computeBasis(m_tempPoints.data(), m_tempPoints.size(), basis);
}
bool isFaceFlipped(uint32_t face) const
{
- const float t1 = m_texcoords[face * 3 + 0].x;
- const float s1 = m_texcoords[face * 3 + 0].y;
- const float t2 = m_texcoords[face * 3 + 1].x;
- const float s2 = m_texcoords[face * 3 + 1].y;
- const float t3 = m_texcoords[face * 3 + 2].x;
- const float s3 = m_texcoords[face * 3 + 2].y;
- const float parametricArea = ((s2 - s1) * (t3 - t1) - (s3 - s1) * (t2 - t1)) / 2;
+ const Vector2 &v1 = m_texcoords[face * 3 + 0];
+ const Vector2 &v2 = m_texcoords[face * 3 + 1];
+ const Vector2 &v3 = m_texcoords[face * 3 + 2];
+ const float parametricArea = ((v2.x - v1.x) * (v3.y - v1.y) - (v3.x - v1.x) * (v2.y - v1.y)) * 0.5f;
return parametricArea < 0.0f;
}
- void computeChartBoundaryEdges(const Chart *chart, Array<uint32_t> *dest) const
+ void parameterizeChart(const Chart *chart)
{
- dest->clear();
- for (uint32_t f = 0; f < chart->faces.size(); f++) {
- const uint32_t face = chart->faces[f];
- for (uint32_t i = 0; i < 3; i++) {
- const uint32_t edge = face * 3 + i;
- if (isChartBoundaryEdge(chart, edge))
- dest->push_back(edge);
+ const uint32_t faceCount = chart->faces.size();
+ for (uint32_t i = 0; i < faceCount; i++) {
+ const uint32_t face = chart->faces[i];
+ for (uint32_t j = 0; j < 3; j++) {
+ const uint32_t offset = face * 3 + j;
+ const Vector3 &pos = m_mesh->position(m_mesh->vertexAt(offset));
+ m_texcoords[offset] = Vector2(dot(chart->basis.tangent, pos), dot(chart->basis.bitangent, pos));
}
}
}
- bool canAddFaceToChart(Chart *chart, uint32_t face)
+ // m_faceCharts for the chart faces must be set to the chart ID. Needed to compute boundary edges.
+ bool isChartParameterizationValid(const Chart *chart)
{
- // Check for flipped triangles.
- if (isFaceFlipped(face))
+ const uint32_t faceCount = chart->faces.size();
+ // Check for flipped faces in the parameterization. OK if all are flipped.
+ uint32_t flippedFaceCount = 0;
+ for (uint32_t i = 0; i < faceCount; i++) {
+ if (isFaceFlipped(chart->faces[i]))
+ flippedFaceCount++;
+ }
+ if (flippedFaceCount != 0 && flippedFaceCount != faceCount)
return false;
- // Find face edges that don't border this chart.
- m_tempEdges1.clear();
- for (uint32_t i = 0; i < 3; i++) {
- const uint32_t edge = face * 3 + i;
- if (isChartBoundaryEdge(chart, edge))
- m_tempEdges1.push_back(edge);
- }
- if (m_tempEdges1.isEmpty())
- return true; // This can happen if the face is surrounded by the chart.
- // Get chart boundary edges, except those that border the face.
- m_tempEdges2.clear();
- for (uint32_t i = 0; i < chart->faces.size(); i++) {
- const uint32_t chartFace = chart->faces[i];
+ // Check for boundary intersection in the parameterization.
+ m_boundaryGrid.reset(m_texcoords.data());
+ for (uint32_t i = 0; i < faceCount; i++) {
+ const uint32_t f = chart->faces[i];
for (uint32_t j = 0; j < 3; j++) {
- const uint32_t chartEdge = chartFace * 3 + j;
- if (!isChartBoundaryEdge(chart, chartEdge))
- continue;
- // Don't check chart boundary edges that border the face.
- const uint32_t oppositeChartEdge = m_mesh->oppositeEdge(chartEdge);
- if (meshEdgeFace(oppositeChartEdge) == face)
- continue;
- m_tempEdges2.push_back(chartEdge);
- }
- }
- const bool intersect = edgeArraysIntersect(m_tempEdges1.data(), m_tempEdges1.size(), m_tempEdges2.data(), m_tempEdges2.size());
-#if 0
- if (intersect) {
- static std::atomic<uint32_t> count = 0;
- char filename[256];
- XA_SPRINTF(filename, sizeof(filename), "intersect%04u.obj", count.fetch_add(1));
- FILE *file;
- XA_FOPEN(file, filename, "w");
- if (file) {
- for (uint32_t i = 0; i < m_texcoords.size(); i++)
- fprintf(file, "v %g %g 0.0\n", m_texcoords[i].x, m_texcoords[i].y);
- fprintf(file, "s off\n");
- fprintf(file, "o face\n");
- {
- fprintf(file, "f ");
- for (uint32_t j = 0; j < 3; j++) {
- const uint32_t index = face * 3 + j + 1; // 1-indexed
- fprintf(file, "%d/%d/%d%c", index, index, index, j == 2 ? '\n' : ' ');
- }
- }
- fprintf(file, "s off\n");
- fprintf(file, "o chart\n");
- for (uint32_t i = 0; i < chart->faces.size(); i++) {
- const uint32_t chartFace = chart->faces[i];
- fprintf(file, "f ");
- for (uint32_t j = 0; j < 3; j++) {
- const uint32_t index = chartFace * 3 + j + 1; // 1-indexed
- fprintf(file, "%d/%d/%d%c", index, index, index, j == 2 ? '\n' : ' ');
- }
- }
- fclose(file);
+ const uint32_t edge = f * 3 + j;
+ if (isChartBoundaryEdge(chart, edge))
+ m_boundaryGrid.append(edge);
}
}
-#endif
- return !intersect;
+ if (m_boundaryGrid.intersectSelf(m_mesh->epsilon()))
+ return false;
+ return true;
}
- bool canMergeCharts(Chart *chart1, Chart *chart2)
+ bool addFaceToChart(Chart *chart, uint32_t face)
{
- for (uint32_t i = 0; i < chart2->faces.size(); i++) {
- if (isFaceFlipped(chart2->faces[i]))
- return false;
+ XA_DEBUG_ASSERT(m_faceCharts[face] == -1);
+ const uint32_t oldFaceCount = chart->faces.size();
+ const bool firstFace = oldFaceCount == 0;
+ // Append the face and any coplanar connected faces to the chart faces array.
+ chart->faces.push_back(face);
+ uint32_t coplanarFace = m_nextPlanarRegionFace[face];
+ while (coplanarFace != face) {
+ XA_DEBUG_ASSERT(m_faceCharts[coplanarFace] == -1);
+ chart->faces.push_back(coplanarFace);
+ coplanarFace = m_nextPlanarRegionFace[coplanarFace];
}
- computeChartBoundaryEdges(chart1, &m_tempEdges1);
- computeChartBoundaryEdges(chart2, &m_tempEdges2);
- return !edgeArraysIntersect(m_tempEdges1.data(), m_tempEdges1.size(), m_tempEdges2.data(), m_tempEdges2.size());
- }
-
- void addFaceToChart(Chart *chart, uint32_t f)
- {
- const bool firstFace = chart->faces.isEmpty();
- // Use the first face normal as the chart basis.
+ const uint32_t faceCount = chart->faces.size();
+ // Compute basis.
+ Basis basis;
if (firstFace) {
- chart->basis.normal = m_faceNormals[f];
- chart->basis.tangent = m_faceTangents[f];
- chart->basis.bitangent = m_faceBitangents[f];
- createFaceTexcoords(chart, f);
- }
- // Add face to chart.
- chart->faces.push_back(f);
- XA_DEBUG_ASSERT(m_faceChartArray[f] == -1);
- m_faceChartArray[f] = chart->id;
- m_facesLeft--;
- // Update area and boundary length.
- chart->area = chart->area + m_faceAreas[f];
- chart->boundaryLength = computeBoundaryLength(chart, f);
- chart->normalSum += m_mesh->triangleNormalAreaScaled(f);
- chart->averageNormal = normalizeSafe(chart->normalSum, Vector3(0), 0.0f);
- chart->centroidSum += m_mesh->triangleCenter(f);
+ // Use the first face normal.
+ // Use any edge as the tangent vector.
+ basis.normal = m_faceNormals[face];
+ basis.tangent = normalize(m_mesh->position(m_mesh->vertexAt(face * 3 + 0)) - m_mesh->position(m_mesh->vertexAt(face * 3 + 1)), kEpsilon);
+ basis.bitangent = cross(basis.normal, basis.tangent);
+ } else {
+ // Use best fit normal.
+ if (!computeChartBasis(chart, &basis)) {
+ chart->faces.resize(oldFaceCount);
+ return false;
+ }
+ if (dot(basis.normal, m_faceNormals[face]) < 0.0f) // Flip normal if oriented in the wrong direction.
+ basis.normal = -basis.normal;
+ }
+ if (!firstFace) {
+ // Compute orthogonal parameterization and check that it is valid.
+ parameterizeChart(chart);
+ for (uint32_t i = oldFaceCount; i < faceCount; i++)
+ m_faceCharts[chart->faces[i]] = chart->id;
+ if (!isChartParameterizationValid(chart)) {
+ for (uint32_t i = oldFaceCount; i < faceCount; i++)
+ m_faceCharts[chart->faces[i]] = -1;
+ chart->faces.resize(oldFaceCount);
+ return false;
+ }
+ }
+ // Add face(s) to chart.
+ chart->basis = basis;
+ chart->area = computeArea(chart, face);
+ chart->boundaryLength = computeBoundaryLength(chart, face);
+ for (uint32_t i = oldFaceCount; i < faceCount; i++) {
+ const uint32_t f = chart->faces[i];
+ m_faceCharts[f] = chart->id;
+ m_facesLeft--;
+ chart->centroidSum += m_mesh->computeFaceCenter(f);
+ }
chart->centroid = chart->centroidSum / float(chart->faces.size());
- // Update candidates.
- updateChartCandidates(chart, f);
- }
-
-#if XA_GROW_CHARTS_COPLANAR
- void growChartCoplanar(Chart *chart)
- {
- XA_DEBUG_ASSERT(!chart->faces.isEmpty());
- for (uint32_t i = 0; i < chart->faces.size(); i++) {
- const uint32_t chartFace = chart->faces[i];
- uint32_t face = m_nextPlanarRegionFace[chartFace];
- while (face != chartFace) {
- // Not assigned to a chart?
- if (m_faceChartArray[face] == -1) {
- createFaceTexcoords(chart, face);
- addFaceToChart(chart, face);
- }
- face = m_nextPlanarRegionFace[face];
+ // Refresh candidates.
+ chart->candidates.clear();
+ for (uint32_t i = 0; i < faceCount; i++) {
+ // Traverse neighboring faces, add the ones that do not belong to any chart yet.
+ const uint32_t f = chart->faces[i];
+ for (uint32_t j = 0; j < 3; j++) {
+ const uint32_t edge = f * 3 + j;
+ const uint32_t oedge = m_mesh->oppositeEdge(edge);
+ if (oedge == UINT32_MAX)
+ continue; // Boundary edge.
+ const uint32_t oface = meshEdgeFace(oedge);
+ if (m_faceCharts[oface] != -1)
+ continue; // Face belongs to another chart.
+ if (chart->failedPlanarRegions.contains(m_facePlanarRegionId[oface]))
+ continue; // Failed to add this faces planar region to the chart before.
+ const float cost = evaluateCost(chart, oface);
+ if (cost < FLT_MAX)
+ chart->candidates.push(cost, oface);
}
}
+ return true;
}
-#endif
+ // Returns true if the seed has changed.
bool relocateSeed(Chart *chart)
{
// Find the first N triangles that fit the proxy best.
const uint32_t faceCount = chart->faces.size();
m_bestTriangles.clear();
for (uint32_t i = 0; i < faceCount; i++) {
- float priority = evaluateProxyFitMetric(chart, chart->faces[i]);
- m_bestTriangles.push(priority, chart->faces[i]);
+ const float cost = evaluateProxyFitMetric(chart, chart->faces[i]);
+ m_bestTriangles.push(cost, chart->faces[i]);
}
// Of those, choose the least central triangle.
uint32_t leastCentral = 0;
float maxDistance = -1;
- const uint32_t bestCount = m_bestTriangles.count();
- for (uint32_t i = 0; i < bestCount; i++) {
- Vector3 faceCentroid = m_mesh->triangleCenter(m_bestTriangles.pairs[i].face);
- float distance = length(chart->centroid - faceCentroid);
+ for (;;) {
+ if (m_bestTriangles.count() == 0)
+ break;
+ const uint32_t face = m_bestTriangles.pop();
+ Vector3 faceCentroid = m_mesh->computeFaceCenter(face);
+ const float distance = length(chart->centroid - faceCentroid);
if (distance > maxDistance) {
maxDistance = distance;
- leastCentral = m_bestTriangles.pairs[i].face;
+ leastCentral = face;
}
}
XA_DEBUG_ASSERT(maxDistance >= 0);
// In order to prevent k-means cyles we record all the previously chosen seeds.
for (uint32_t i = 0; i < chart->seeds.size(); i++) {
- if (chart->seeds[i] == leastCentral) {
+ // Treat seeds belong to the same planar region as equal.
+ if (chart->seeds[i] == leastCentral || m_facePlanarRegionId[chart->seeds[i]] == m_facePlanarRegionId[leastCentral]) {
// Move new seed to the end of the seed array.
uint32_t last = chart->seeds.size() - 1;
swap(chart->seeds[i], chart->seeds[last]);
@@ -4907,26 +5427,32 @@ private:
// Evaluate combined metric.
float evaluateCost(Chart *chart, uint32_t face) const
{
+ if (dot(m_faceNormals[face], chart->basis.normal) <= 0.26f) // ~75 degrees
+ return FLT_MAX;
// Estimate boundary length and area:
- const float newChartArea = chart->area + m_faceAreas[face];
- const float newBoundaryLength = computeBoundaryLength(chart, face);
+ float newChartArea = 0.0f, newBoundaryLength = 0.0f;
+ if (m_options.maxChartArea > 0.0f || m_options.roundnessMetricWeight > 0.0f)
+ newChartArea = computeArea(chart, face);
+ if (m_options.maxBoundaryLength > 0.0f || m_options.roundnessMetricWeight > 0.0f)
+ newBoundaryLength = computeBoundaryLength(chart, face);
// Enforce limits strictly:
if (m_options.maxChartArea > 0.0f && newChartArea > m_options.maxChartArea)
return FLT_MAX;
if (m_options.maxBoundaryLength > 0.0f && newBoundaryLength > m_options.maxBoundaryLength)
return FLT_MAX;
- if (dot(m_faceNormals[face], chart->averageNormal) < 0.5f)
- return FLT_MAX;
- // Penalize faces that cross seams, reward faces that close seams or reach boundaries.
- // Make sure normal seams are fully respected:
- const float N = evaluateNormalSeamMetric(chart, face);
- if (m_options.normalSeamMetricWeight >= 1000.0f && N > 0.0f)
- return FLT_MAX;
- float cost = m_options.normalSeamMetricWeight * N;
+ float cost = 0.0f;
+ if (m_options.normalSeamMetricWeight > 0.0f) {
+ // Penalize faces that cross seams, reward faces that close seams or reach boundaries.
+ // Make sure normal seams are fully respected:
+ const float N = evaluateNormalSeamMetric(chart, face);
+ if (m_options.normalSeamMetricWeight >= 1000.0f && N > 0.0f)
+ return FLT_MAX;
+ cost += m_options.normalSeamMetricWeight * N;
+ }
if (m_options.proxyFitMetricWeight > 0.0f)
cost += m_options.proxyFitMetricWeight * evaluateProxyFitMetric(chart, face);
if (m_options.roundnessMetricWeight > 0.0f)
- cost += m_options.roundnessMetricWeight * evaluateRoundnessMetric(chart, face, newBoundaryLength, newChartArea);
+ cost += m_options.roundnessMetricWeight * evaluateRoundnessMetric(chart, newBoundaryLength, newChartArea);
if (m_options.straightnessMetricWeight > 0.0f)
cost += m_options.straightnessMetricWeight * evaluateStraightnessMetric(chart, face);
if (m_options.textureSeamMetricWeight > 0.0f)
@@ -4941,40 +5467,45 @@ private:
}
// Returns a value in [0-1].
- float evaluateProxyFitMetric(Chart *chart, uint32_t f) const
+ float evaluateProxyFitMetric(Chart *chart, uint32_t face) const
{
- const Vector3 faceNormal = m_faceNormals[f];
+ // All faces in coplanar regions have the same normal, can use any face.
+ const Vector3 faceNormal = m_faceNormals[face];
// Use plane fitting metric for now:
- return 1 - dot(faceNormal, chart->averageNormal); // @@ normal deviations should be weighted by face area
+ return 1 - dot(faceNormal, chart->basis.normal); // @@ normal deviations should be weighted by face area
}
- float evaluateRoundnessMetric(Chart *chart, uint32_t /*face*/, float newBoundaryLength, float newChartArea) const
+ float evaluateRoundnessMetric(Chart *chart, float newBoundaryLength, float newChartArea) const
{
- float roundness = square(chart->boundaryLength) / chart->area;
- float newRoundness = square(newBoundaryLength) / newChartArea;
- if (newRoundness > roundness) {
- return square(newBoundaryLength) / (newChartArea * 4.0f * kPi);
- } else {
- // Offer no impedance to faces that improve roundness.
- return 0;
- }
+ const float roundness = square(chart->boundaryLength) / chart->area;
+ const float newBoundaryLengthSq = square(newBoundaryLength);
+ const float newRoundness = newBoundaryLengthSq / newChartArea;
+ if (newRoundness > roundness)
+ return newBoundaryLengthSq / (newChartArea * kPi4);
+ // Offer no impedance to faces that improve roundness.
+ return 0;
}
- float evaluateStraightnessMetric(Chart *chart, uint32_t f) const
+ float evaluateStraightnessMetric(Chart *chart, uint32_t firstFace) const
{
- float l_out = 0.0f;
- float l_in = 0.0f;
- for (Mesh::FaceEdgeIterator it(m_mesh, f); !it.isDone(); it.advance()) {
- float l = m_edgeLengths[it.edge()];
- if (it.isBoundary() || m_ignoreFaces[it.oppositeFace()]) {
- l_out += l;
- } else {
- if (m_faceChartArray[it.oppositeFace()] != chart->id) {
+ float l_out = 0.0f, l_in = 0.0f;
+ const uint32_t planarRegionId = m_facePlanarRegionId[firstFace];
+ uint32_t face = firstFace;
+ for (;;) {
+ for (Mesh::FaceEdgeIterator it(m_mesh, face); !it.isDone(); it.advance()) {
+ const float l = m_edgeLengths[it.edge()];
+ if (it.isBoundary()) {
l_out += l;
- } else {
- l_in += l;
+ } else if (m_facePlanarRegionId[it.oppositeFace()] != planarRegionId) {
+ if (m_faceCharts[it.oppositeFace()] != chart->id)
+ l_out += l;
+ else
+ l_in += l;
}
}
+ face = m_nextPlanarRegionFace[face];
+ if (face == firstFace)
+ break;
}
XA_DEBUG_ASSERT(l_in != 0.0f); // Candidate face must be adjacent to chart. @@ This is not true if the input mesh has zero-length edges.
float ratio = (l_out - l_in) / (l_out + l_in);
@@ -4991,128 +5522,184 @@ private:
const uint32_t v1 = m_mesh->vertexAt(meshEdgeIndex1(edge));
const uint32_t ov0 = m_mesh->vertexAt(meshEdgeIndex0(oppositeEdge));
const uint32_t ov1 = m_mesh->vertexAt(meshEdgeIndex1(oppositeEdge));
- return m_mesh->normal(v0) != m_mesh->normal(ov1) || m_mesh->normal(v1) != m_mesh->normal(ov0);
+ if (v0 == ov1 && v1 == ov0)
+ return false;
+ return !equal(m_mesh->normal(v0), m_mesh->normal(ov1), kNormalEpsilon) || !equal(m_mesh->normal(v1), m_mesh->normal(ov0), kNormalEpsilon);
}
- return m_faceNormals[meshEdgeFace(edge)] != m_faceNormals[meshEdgeFace(oppositeEdge)];
+ const uint32_t f0 = meshEdgeFace(edge);
+ const uint32_t f1 = meshEdgeFace(oppositeEdge);
+ if (m_facePlanarRegionId[f0] == m_facePlanarRegionId[f1])
+ return false;
+ return !equal(m_faceNormals[f0], m_faceNormals[f1], kNormalEpsilon);
}
- float evaluateNormalSeamMetric(Chart *chart, uint32_t f) const
+ float evaluateNormalSeamMetric(Chart *chart, uint32_t firstFace) const
{
- float seamFactor = 0.0f;
- float totalLength = 0.0f;
- for (Mesh::FaceEdgeIterator it(m_mesh, f); !it.isDone(); it.advance()) {
- if (it.isBoundary() || m_ignoreFaces[it.oppositeFace()])
- continue;
- if (m_faceChartArray[it.oppositeFace()] != chart->id)
- continue;
- float l = m_edgeLengths[it.edge()];
- totalLength += l;
- if (!it.isSeam())
- continue;
- // Make sure it's a normal seam.
- if (isNormalSeam(it.edge())) {
- float d;
- if (m_mesh->flags() & MeshFlags::HasNormals) {
- const Vector3 &n0 = m_mesh->normal(it.vertex0());
- const Vector3 &n1 = m_mesh->normal(it.vertex1());
- const Vector3 &on0 = m_mesh->normal(m_mesh->vertexAt(meshEdgeIndex0(it.oppositeEdge())));
- const Vector3 &on1 = m_mesh->normal(m_mesh->vertexAt(meshEdgeIndex1(it.oppositeEdge())));
- const float d0 = clamp(dot(n0, on1), 0.0f, 1.0f);
- const float d1 = clamp(dot(n1, on0), 0.0f, 1.0f);
- d = (d0 + d1) * 0.5f;
- } else {
- d = clamp(dot(m_faceNormals[f], m_faceNormals[meshEdgeFace(it.oppositeEdge())]), 0.0f, 1.0f);
+ float seamFactor = 0.0f, totalLength = 0.0f;
+ uint32_t face = firstFace;
+ for (;;) {
+ for (Mesh::FaceEdgeIterator it(m_mesh, face); !it.isDone(); it.advance()) {
+ if (it.isBoundary())
+ continue;
+ if (m_faceCharts[it.oppositeFace()] != chart->id)
+ continue;
+ float l = m_edgeLengths[it.edge()];
+ totalLength += l;
+ if (!it.isSeam())
+ continue;
+ // Make sure it's a normal seam.
+ if (isNormalSeam(it.edge())) {
+ float d;
+ if (m_mesh->flags() & MeshFlags::HasNormals) {
+ const Vector3 &n0 = m_mesh->normal(it.vertex0());
+ const Vector3 &n1 = m_mesh->normal(it.vertex1());
+ const Vector3 &on0 = m_mesh->normal(m_mesh->vertexAt(meshEdgeIndex0(it.oppositeEdge())));
+ const Vector3 &on1 = m_mesh->normal(m_mesh->vertexAt(meshEdgeIndex1(it.oppositeEdge())));
+ const float d0 = clamp(dot(n0, on1), 0.0f, 1.0f);
+ const float d1 = clamp(dot(n1, on0), 0.0f, 1.0f);
+ d = (d0 + d1) * 0.5f;
+ } else {
+ d = clamp(dot(m_faceNormals[face], m_faceNormals[meshEdgeFace(it.oppositeEdge())]), 0.0f, 1.0f);
+ }
+ l *= 1 - d;
+ seamFactor += l;
}
- l *= 1 - d;
- seamFactor += l;
}
+ face = m_nextPlanarRegionFace[face];
+ if (face == firstFace)
+ break;
}
if (seamFactor <= 0.0f)
return 0.0f;
return seamFactor / totalLength;
}
- float evaluateTextureSeamMetric(Chart *chart, uint32_t f) const
+ float evaluateTextureSeamMetric(Chart *chart, uint32_t firstFace) const
{
- float seamLength = 0.0f;
- float totalLength = 0.0f;
- for (Mesh::FaceEdgeIterator it(m_mesh, f); !it.isDone(); it.advance()) {
- if (it.isBoundary() || m_ignoreFaces[it.oppositeFace()])
- continue;
- if (m_faceChartArray[it.oppositeFace()] != chart->id)
- continue;
- float l = m_edgeLengths[it.edge()];
- totalLength += l;
- if (!it.isSeam())
- continue;
- // Make sure it's a texture seam.
- if (it.isTextureSeam())
- seamLength += l;
+ float seamLength = 0.0f, totalLength = 0.0f;
+ uint32_t face = firstFace;
+ for (;;) {
+ for (Mesh::FaceEdgeIterator it(m_mesh, face); !it.isDone(); it.advance()) {
+ if (it.isBoundary())
+ continue;
+ if (m_faceCharts[it.oppositeFace()] != chart->id)
+ continue;
+ float l = m_edgeLengths[it.edge()];
+ totalLength += l;
+ if (!it.isSeam())
+ continue;
+ // Make sure it's a texture seam.
+ if (it.isTextureSeam())
+ seamLength += l;
+ }
+ face = m_nextPlanarRegionFace[face];
+ if (face == firstFace)
+ break;
}
- if (seamLength == 0.0f)
+ if (seamLength <= 0.0f)
return 0.0f; // Avoid division by zero.
return seamLength / totalLength;
}
- float computeBoundaryLength(Chart *chart, uint32_t f) const
+ float computeArea(Chart *chart, uint32_t firstFace) const
+ {
+ float area = chart->area;
+ uint32_t face = firstFace;
+ for (;;) {
+ area += m_faceAreas[face];
+ face = m_nextPlanarRegionFace[face];
+ if (face == firstFace)
+ break;
+ }
+ return area;
+ }
+
+ float computeBoundaryLength(Chart *chart, uint32_t firstFace) const
{
float boundaryLength = chart->boundaryLength;
// Add new edges, subtract edges shared with the chart.
- for (Mesh::FaceEdgeIterator it(m_mesh, f); !it.isDone(); it.advance()) {
- const float edgeLength = m_edgeLengths[it.edge()];
- if (it.isBoundary() || m_ignoreFaces[it.oppositeFace()]) {
- boundaryLength += edgeLength;
- } else {
- if (m_faceChartArray[it.oppositeFace()] != chart->id)
+ const uint32_t planarRegionId = m_facePlanarRegionId[firstFace];
+ uint32_t face = firstFace;
+ for (;;) {
+ for (Mesh::FaceEdgeIterator it(m_mesh, face); !it.isDone(); it.advance()) {
+ const float edgeLength = m_edgeLengths[it.edge()];
+ if (it.isBoundary()) {
boundaryLength += edgeLength;
- else
- boundaryLength -= edgeLength;
+ } else if (m_facePlanarRegionId[it.oppositeFace()] != planarRegionId) {
+ if (m_faceCharts[it.oppositeFace()] != chart->id)
+ boundaryLength += edgeLength;
+ else
+ boundaryLength -= edgeLength;
+ }
}
+ face = m_nextPlanarRegionFace[face];
+ if (face == firstFace)
+ break;
}
return max(0.0f, boundaryLength); // @@ Hack!
}
- void mergeChart(Chart *owner, Chart *chart, float sharedBoundaryLength)
+ bool mergeChart(Chart *owner, Chart *chart, float sharedBoundaryLength)
{
- const uint32_t faceCount = chart->faces.size();
- for (uint32_t i = 0; i < faceCount; i++) {
- uint32_t f = chart->faces[i];
- XA_DEBUG_ASSERT(m_faceChartArray[f] == chart->id);
- m_faceChartArray[f] = owner->id;
- owner->faces.push_back(f);
+ const uint32_t oldOwnerFaceCount = owner->faces.size();
+ const uint32_t chartFaceCount = chart->faces.size();
+ owner->faces.push_back(chart->faces);
+ for (uint32_t i = 0; i < chartFaceCount; i++) {
+ XA_DEBUG_ASSERT(m_faceCharts[chart->faces[i]] == chart->id);
+ m_faceCharts[chart->faces[i]] = owner->id;
+ }
+ // Compute basis using best fit normal.
+ Basis basis;
+ if (!computeChartBasis(owner, &basis)) {
+ owner->faces.resize(oldOwnerFaceCount);
+ for (uint32_t i = 0; i < chartFaceCount; i++)
+ m_faceCharts[chart->faces[i]] = chart->id;
+ return false;
+ }
+ if (dot(basis.normal, m_faceNormals[owner->faces[0]]) < 0.0f) // Flip normal if oriented in the wrong direction.
+ basis.normal = -basis.normal;
+ // Compute orthogonal parameterization and check that it is valid.
+ parameterizeChart(owner);
+ if (!isChartParameterizationValid(owner)) {
+ owner->faces.resize(oldOwnerFaceCount);
+ for (uint32_t i = 0; i < chartFaceCount; i++)
+ m_faceCharts[chart->faces[i]] = chart->id;
+ return false;
}
+ // Merge chart.
+ owner->basis = basis;
+ owner->failedPlanarRegions.push_back(chart->failedPlanarRegions);
// Update adjacencies?
owner->area += chart->area;
owner->boundaryLength += chart->boundaryLength - sharedBoundaryLength;
- owner->normalSum += chart->normalSum;
- owner->averageNormal = normalizeSafe(owner->normalSum, Vector3(0), 0.0f);
// Delete chart.
- m_chartArray[chart->id] = nullptr;
+ m_charts[chart->id] = nullptr;
chart->~Chart();
XA_FREE(chart);
+ return true;
}
const Mesh *m_mesh;
- const Array<uint32_t> *m_meshFaces;
- Array<bool> m_ignoreFaces;
Array<float> m_edgeLengths;
Array<float> m_faceAreas;
Array<Vector3> m_faceNormals;
- Array<Vector3> m_faceTangents;
- Array<Vector3> m_faceBitangents;
Array<Vector2> m_texcoords;
uint32_t m_facesLeft;
- Array<int> m_faceChartArray;
- Array<Chart *> m_chartArray;
- PriorityQueue m_bestTriangles;
+ Array<int> m_faceCharts;
+ Array<Chart *> m_charts;
+ CostQueue m_bestTriangles;
KISSRng m_rand;
ChartOptions m_options;
- Array<Chart *> m_faceCandidateCharts;
- Array<float> m_faceCandidateCosts;
-#if XA_GROW_CHARTS_COPLANAR
Array<uint32_t> m_nextPlanarRegionFace;
+ Array<uint32_t> m_facePlanarRegionId;
+ Array<Vector3> m_tempPoints;
+ UniformGrid2 m_boundaryGrid;
+#if XA_MERGE_CHARTS
+ // mergeCharts
+ Array<float> m_sharedBoundaryLengths;
+ Array<float> m_sharedBoundaryLengthsNoSeams;
+ Array<uint32_t> m_sharedBoundaryEdgeCountNoSeams;
#endif
- Array<uint32_t> m_tempEdges1, m_tempEdges2;
};
} // namespace segment
@@ -5301,7 +5888,11 @@ private:
// q = A·p
sparse::mult(A, p, q);
// alpha = delta_new / p·q
- alpha = delta_new / sparse::dot(p, q);
+ const float pdotq = sparse::dot(p, q);
+ if (!isFinite(pdotq) || isNan(pdotq))
+ alpha = 0.0f;
+ else
+ alpha = delta_new / pdotq;
// x = alfa·p + x
sparse::saxpy(alpha, p, x);
if ((i & 31) == 0) { // recompute r after 32 steps
@@ -5514,186 +6105,518 @@ static bool computeLeastSquaresConformalMap(Mesh *mesh)
// Solve
Solver::LeastSquaresSolver(A, b, x, lockedParameters, 4, 0.000001f);
// Map x back to texcoords:
- for (uint32_t v = 0; v < vertexCount; v++)
+ for (uint32_t v = 0; v < vertexCount; v++) {
mesh->texcoord(v) = Vector2(x[2 * v + 0], x[2 * v + 1]);
+ XA_DEBUG_ASSERT(!isNan(mesh->texcoord(v).x));
+ XA_DEBUG_ASSERT(!isNan(mesh->texcoord(v).y));
+ }
return true;
}
-static bool computeOrthogonalProjectionMap(Mesh *mesh)
+#if XA_RECOMPUTE_CHARTS
+struct PiecewiseParam
{
- uint32_t vertexCount = mesh->vertexCount();
- // Avoid redundant computations.
- float matrix[6];
- Fit::computeCovariance(vertexCount, &mesh->position(0), matrix);
- if (matrix[0] == 0 && matrix[3] == 0 && matrix[5] == 0)
- return false;
- float eigenValues[3];
- Vector3 eigenVectors[3];
- if (!Fit::eigenSolveSymmetric3(matrix, eigenValues, eigenVectors))
- return false;
- Vector3 axis[2];
- axis[0] = normalize(eigenVectors[0], kEpsilon);
- axis[1] = normalize(eigenVectors[1], kEpsilon);
- // Project vertices to plane.
- for (uint32_t i = 0; i < vertexCount; i++)
- mesh->texcoord(i) = Vector2(dot(axis[0], mesh->position(i)), dot(axis[1], mesh->position(i)));
- return true;
-}
+ void reset(const Mesh *mesh, uint32_t faceCount)
+ {
+ m_mesh = mesh;
+ m_faceCount = faceCount;
+ const uint32_t vertexCount = m_mesh->vertexCount();
+ m_texcoords.resize(vertexCount);
+ m_patch.reserve(m_faceCount);
+ m_faceAssigned.resize(m_faceCount);
+ m_faceAssigned.zeroOutMemory();
+ m_faceInvalid.resize(m_faceCount);
+ m_faceInPatch.resize(m_faceCount);
+ m_vertexInPatch.resize(vertexCount);
+ m_faceInCandidates.resize(m_faceCount);
+ }
+
+ ConstArrayView<uint32_t> chartFaces() const { return m_patch; }
+ const Vector2 *texcoords() const { return m_texcoords.data(); }
+
+ bool computeChart()
+ {
+ m_patch.clear();
+ m_faceInvalid.zeroOutMemory();
+ m_faceInPatch.zeroOutMemory();
+ m_vertexInPatch.zeroOutMemory();
+ // Add the seed face (first unassigned face) to the patch.
+ uint32_t seed = UINT32_MAX;
+ for (uint32_t f = 0; f < m_faceCount; f++) {
+ if (m_faceAssigned.get(f))
+ continue;
+ seed = f;
+ m_patch.push_back(seed);
+ m_faceInPatch.set(seed);
+ m_faceAssigned.set(seed);
+ Vector2 texcoords[3];
+ orthoProjectFace(seed, texcoords);
+ for (uint32_t i = 0; i < 3; i++) {
+ const uint32_t vertex = m_mesh->vertexAt(seed * 3 + i);
+ m_vertexInPatch.set(vertex);
+ m_texcoords[vertex] = texcoords[i];
+ }
+ break;
+ }
+ if (seed == UINT32_MAX)
+ return false;
+ for (;;) {
+ findCandidates();
+ if (m_candidates.isEmpty())
+ break;
+ for (;;) {
+ // Find the candidate with the lowest cost.
+ float lowestCost = FLT_MAX;
+ uint32_t bestCandidate = UINT32_MAX;
+ for (uint32_t i = 0; i < m_candidates.size(); i++) {
+ const Candidate &candidate = m_candidates[i];
+ if (m_faceInvalid.get(candidate.face)) // A candidate face may be invalidated after is was added.
+ continue;
+ if (candidate.maxCost < lowestCost) {
+ lowestCost = candidate.maxCost;
+ bestCandidate = i;
+ }
+ }
+ if (bestCandidate == UINT32_MAX)
+ break;
+ // Compute the position by averaging linked candidates (candidates that share the same free vertex).
+ Vector2 position(0.0f);
+ uint32_t n = 0;
+ for (CandidateIterator it(m_candidates, bestCandidate); !it.isDone(); it.advance()) {
+ position += it.current().position;
+ n++;
+ }
+ position *= 1.0f / (float)n;
+ const uint32_t freeVertex = m_candidates[bestCandidate].vertex;
+ XA_DEBUG_ASSERT(!isNan(position.x));
+ XA_DEBUG_ASSERT(!isNan(position.y));
+ m_texcoords[freeVertex] = position;
+ // Check for flipped faces. This is also done when candidates are first added, but the averaged position of the free vertex is different now, so check again.
+ bool invalid = false;
+ for (CandidateIterator it(m_candidates, bestCandidate); !it.isDone(); it.advance()) {
+ const uint32_t vertex0 = m_mesh->vertexAt(meshEdgeIndex0(it.current().patchEdge));
+ const uint32_t vertex1 = m_mesh->vertexAt(meshEdgeIndex1(it.current().patchEdge));
+ const float freeVertexOrient = orientToEdge(m_texcoords[vertex0], m_texcoords[vertex1], position);
+ if ((it.current().patchVertexOrient < 0.0f && freeVertexOrient < 0.0f) || (it.current().patchVertexOrient > 0.0f && freeVertexOrient > 0.0f)) {
+ invalid = true;
+ break;
+ }
+ }
+ // Check for boundary intersection.
+ if (!invalid) {
+ m_boundaryGrid.reset(m_texcoords.data(), m_mesh->indices());
+ // Add edges on the patch boundary to the grid.
+ // Temporarily adding candidate faces to the patch makes it simpler to detect which edges are on the boundary.
+ const uint32_t oldPatchSize = m_patch.size();
+ for (CandidateIterator it(m_candidates, bestCandidate); !it.isDone(); it.advance())
+ m_patch.push_back(it.current().face);
+ for (uint32_t i = 0; i < m_patch.size(); i++) {
+ for (Mesh::FaceEdgeIterator it(m_mesh, m_patch[i]); !it.isDone(); it.advance()) {
+ const uint32_t oface = it.oppositeFace();
+ if (oface == UINT32_MAX || oface >= m_faceCount || !m_faceInPatch.get(oface))
+ m_boundaryGrid.append(it.edge());
+ }
+ }
+ invalid = m_boundaryGrid.intersectSelf(m_mesh->epsilon());
+ m_patch.resize(oldPatchSize);
+ }
+ if (invalid) {
+ // Mark all faces of linked candidates as invalid.
+ for (CandidateIterator it(m_candidates, bestCandidate); !it.isDone(); it.advance())
+ m_faceInvalid.set(it.current().face);
+ continue;
+ }
+ // Add faces to the patch.
+ for (CandidateIterator it(m_candidates, bestCandidate); !it.isDone(); it.advance()) {
+ m_patch.push_back(it.current().face);
+ m_faceInPatch.set(it.current().face);
+ m_faceAssigned.set(it.current().face);
+ }
+ // Add vertex to the patch.
+ m_vertexInPatch.set(freeVertex);
+ // Successfully added candidate face(s) to patch.
+ break;
+ }
+ }
+ return true;
+ }
+
+private:
+ struct Candidate
+ {
+ uint32_t face, vertex;
+ uint32_t next; // The next candidate with the same vertex.
+ Vector2 position;
+ float cost;
+ float maxCost; // Of all linked candidates.
+ uint32_t patchEdge;
+ float patchVertexOrient;
+ };
+
+ struct CandidateIterator
+ {
+ CandidateIterator(Array<Candidate> &candidates, uint32_t first) : m_candidates(candidates), m_current(first) {}
+ void advance() { if (m_current != UINT32_MAX) m_current = m_candidates[m_current].next; }
+ bool isDone() const { return m_current == UINT32_MAX; }
+ Candidate &current() { return m_candidates[m_current]; }
+
+ private:
+ Array<Candidate> &m_candidates;
+ uint32_t m_current;
+ };
+
+ const Mesh *m_mesh;
+ uint32_t m_faceCount;
+ Array<Vector2> m_texcoords;
+ Array<Candidate> m_candidates;
+ BitArray m_faceInCandidates;
+ Array<uint32_t> m_patch;
+ BitArray m_faceAssigned; // Face is assigned to a previous chart or the current patch.
+ BitArray m_faceInPatch, m_vertexInPatch;
+ BitArray m_faceInvalid; // Face cannot be added to the patch - flipped, cost too high or causes boundary intersection.
+ UniformGrid2 m_boundaryGrid;
+
+ // Find candidate faces on the patch front.
+ void findCandidates()
+ {
+ m_candidates.clear();
+ m_faceInCandidates.zeroOutMemory();
+ for (uint32_t i = 0; i < m_patch.size(); i++) {
+ for (Mesh::FaceEdgeIterator it(m_mesh, m_patch[i]); !it.isDone(); it.advance()) {
+ const uint32_t oface = it.oppositeFace();
+ if (oface == UINT32_MAX || oface >= m_faceCount || m_faceAssigned.get(oface) || m_faceInCandidates.get(oface))
+ continue;
+ // Found an active edge on the patch front.
+ // Find the free vertex (the vertex that isn't on the active edge).
+ // Compute the orientation of the other patch face vertex to the active edge.
+ uint32_t freeVertex = UINT32_MAX;
+ float orient = 0.0f;
+ for (uint32_t j = 0; j < 3; j++) {
+ const uint32_t vertex = m_mesh->vertexAt(oface * 3 + j);
+ if (vertex != it.vertex0() && vertex != it.vertex1()) {
+ freeVertex = vertex;
+ orient = orientToEdge(m_texcoords[it.vertex0()], m_texcoords[it.vertex1()], m_texcoords[m_mesh->vertexAt(m_patch[i] * 3 + j)]);
+ break;
+ }
+ }
+ XA_DEBUG_ASSERT(freeVertex != UINT32_MAX);
+ // If the free vertex is already in the patch, the face is enclosed by the patch. Add the face to the patch - don't need to assign texcoords.
+ if (m_vertexInPatch.get(freeVertex)) {
+ freeVertex = UINT32_MAX;
+ m_patch.push_back(oface);
+ m_faceAssigned.set(oface);
+ continue;
+ }
+ // Check this here rather than above so faces enclosed by the patch are always added.
+ if (m_faceInvalid.get(oface))
+ continue;
+ addCandidateFace(it.edge(), orient, oface, it.oppositeEdge(), freeVertex);
+ }
+ }
+ // Link candidates that share the same vertex.
+ for (uint32_t i = 0; i < m_candidates.size(); i++) {
+ if (m_candidates[i].next != UINT32_MAX)
+ continue;
+ uint32_t current = i;
+ for (uint32_t j = i + 1; j < m_candidates.size(); j++) {
+ if (m_candidates[j].vertex == m_candidates[current].vertex) {
+ m_candidates[current].next = j;
+ current = j;
+ }
+ }
+ }
+ // Set max cost for linked candidates.
+ for (uint32_t i = 0; i < m_candidates.size(); i++) {
+ float maxCost = 0.0f;
+ for (CandidateIterator it(m_candidates, i); !it.isDone(); it.advance())
+ maxCost = max(maxCost, it.current().cost);
+ for (CandidateIterator it(m_candidates, i); !it.isDone(); it.advance())
+ it.current().maxCost = maxCost;
+ }
+ }
+
+ void addCandidateFace(uint32_t patchEdge, float patchVertexOrient, uint32_t face, uint32_t edge, uint32_t freeVertex)
+ {
+ Vector2 texcoords[3];
+ orthoProjectFace(face, texcoords);
+ // Find corresponding vertices between the patch edge and candidate edge.
+ const uint32_t vertex0 = m_mesh->vertexAt(meshEdgeIndex0(patchEdge));
+ const uint32_t vertex1 = m_mesh->vertexAt(meshEdgeIndex1(patchEdge));
+ uint32_t localVertex0 = UINT32_MAX, localVertex1 = UINT32_MAX, localFreeVertex = UINT32_MAX;
+ for (uint32_t i = 0; i < 3; i++) {
+ const uint32_t vertex = m_mesh->vertexAt(face * 3 + i);
+ if (vertex == m_mesh->vertexAt(meshEdgeIndex1(edge)))
+ localVertex0 = i;
+ else if (vertex == m_mesh->vertexAt(meshEdgeIndex0(edge)))
+ localVertex1 = i;
+ else
+ localFreeVertex = i;
+ }
+ // Scale orthogonal projection to match the patch edge.
+ const Vector2 patchEdgeVec = m_texcoords[vertex1] - m_texcoords[vertex0];
+ const Vector2 localEdgeVec = texcoords[localVertex1] - texcoords[localVertex0];
+ const float len1 = length(patchEdgeVec);
+ const float len2 = length(localEdgeVec);
+ const float scale = len1 / len2;
+ XA_ASSERT(scale > 0.0f);
+ for (uint32_t i = 0; i < 3; i++)
+ texcoords[i] *= scale;
+ // Translate to the first vertex on the patch edge.
+ const Vector2 translate = m_texcoords[vertex0] - texcoords[localVertex0];
+ for (uint32_t i = 0; i < 3; i++)
+ texcoords[i] += translate;
+ // Compute the angle between the patch edge and the corresponding local edge.
+ const float angle = atan2f(patchEdgeVec.y, patchEdgeVec.x) - atan2f(localEdgeVec.y, localEdgeVec.x);
+ // Rotate so the patch edge and the corresponding local edge occupy the same space.
+ for (uint32_t i = 0; i < 3; i++) {
+ if (i == localVertex0)
+ continue;
+ Vector2 &uv = texcoords[i];
+ uv -= texcoords[localVertex0]; // Rotate around the first vertex.
+ const float c = cosf(angle);
+ const float s = sinf(angle);
+ const float x = uv.x * c - uv.y * s;
+ const float y = uv.y * c + uv.x * s;
+ uv.x = x + texcoords[localVertex0].x;
+ uv.y = y + texcoords[localVertex0].y;
+ }
+ // Check for local overlap (flipped triangle).
+ // The patch face vertex that isn't on the active edge and the free vertex should be oriented on opposite sides to the active edge.
+ const float freeVertexOrient = orientToEdge(m_texcoords[vertex0], m_texcoords[vertex1], texcoords[localFreeVertex]);
+ if ((patchVertexOrient < 0.0f && freeVertexOrient < 0.0f) || (patchVertexOrient > 0.0f && freeVertexOrient > 0.0f)) {
+ m_faceInvalid.set(face);
+ return;
+ }
+ const float stretch = computeStretch(m_mesh->position(vertex0), m_mesh->position(vertex1), m_mesh->position(freeVertex), texcoords[0], texcoords[1], texcoords[2]);
+ if (stretch >= FLT_MAX) {
+ m_faceInvalid.set(face);
+ return;
+ }
+ const float cost = fabsf(stretch - 1.0f);
+#if 0
+ if (cost > 0.25f) {
+ m_faceInvalid.set(face);
+ return;
+ }
+#endif
+ // Add the candidate.
+ Candidate candidate;
+ candidate.face = face;
+ candidate.vertex = freeVertex;
+ candidate.position = texcoords[localFreeVertex];
+ candidate.next = UINT32_MAX;
+ candidate.cost = cost;
+ candidate.patchEdge = patchEdge;
+ candidate.patchVertexOrient = patchVertexOrient;
+ m_candidates.push_back(candidate);
+ m_faceInCandidates.set(face);
+ }
+
+ void orthoProjectFace(uint32_t face, Vector2 *texcoords) const
+ {
+ const Vector3 normal = m_mesh->computeFaceNormal(face);
+ const Vector3 tangent = normalize(m_mesh->position(m_mesh->vertexAt(face * 3 + 1)) - m_mesh->position(m_mesh->vertexAt(face * 3 + 0)), kEpsilon);
+ const Vector3 bitangent = cross(normal, tangent);
+ for (uint32_t i = 0; i < 3; i++) {
+ const Vector3 &pos = m_mesh->position(m_mesh->vertexAt(face * 3 + i));
+ texcoords[i] = Vector2(dot(tangent, pos), dot(bitangent, pos));
+ }
+ }
+
+ float parametricArea(const Vector2 *texcoords) const
+ {
+ const Vector2 &v1 = texcoords[0];
+ const Vector2 &v2 = texcoords[1];
+ const Vector2 &v3 = texcoords[2];
+ return ((v2.x - v1.x) * (v3.y - v1.y) - (v3.x - v1.x) * (v2.y - v1.y)) * 0.5f;
+ }
+
+ float computeStretch(Vector3 p1, Vector3 p2, Vector3 p3, Vector2 t1, Vector2 t2, Vector2 t3) const
+ {
+ float parametricArea = ((t2.y - t1.y) * (t3.x - t1.x) - (t3.y - t1.y) * (t2.x - t1.x)) * 0.5f;
+ if (isZero(parametricArea, kAreaEpsilon))
+ return FLT_MAX;
+ if (parametricArea < 0.0f)
+ parametricArea = fabsf(parametricArea);
+ const float geometricArea = length(cross(p2 - p1, p3 - p1)) * 0.5f;
+ if (parametricArea <= geometricArea)
+ return parametricArea / geometricArea;
+ else
+ return geometricArea / parametricArea;
+ }
+
+ // Return value is positive if the point is one side of the edge, negative if on the other side.
+ float orientToEdge(Vector2 edgeVertex0, Vector2 edgeVertex1, Vector2 point) const
+ {
+ return (edgeVertex0.x - point.x) * (edgeVertex1.y - point.y) - (edgeVertex0.y - point.y) * (edgeVertex1.x - point.x);
+ }
+};
+#endif
// Estimate quality of existing parameterization.
-struct ParameterizationQuality
+struct Quality
{
+ // computeBoundaryIntersection
+ bool boundaryIntersection = false;
+
+ // computeFlippedFaces
uint32_t totalTriangleCount = 0;
uint32_t flippedTriangleCount = 0;
uint32_t zeroAreaTriangleCount = 0;
- float parametricArea = 0.0f;
- float geometricArea = 0.0f;
+
+ // computeMetrics
+ float totalParametricArea = 0.0f;
+ float totalGeometricArea = 0.0f;
float stretchMetric = 0.0f;
float maxStretchMetric = 0.0f;
float conformalMetric = 0.0f;
float authalicMetric = 0.0f;
- bool boundaryIntersection = false;
-};
-static ParameterizationQuality calculateParameterizationQuality(const Mesh *mesh, uint32_t faceCount, Array<uint32_t> *flippedFaces)
-{
- XA_DEBUG_ASSERT(mesh != nullptr);
- ParameterizationQuality quality;
- uint32_t firstBoundaryEdge = UINT32_MAX;
- for (uint32_t e = 0; e < mesh->edgeCount(); e++) {
- if (mesh->isBoundaryEdge(e)) {
- firstBoundaryEdge = e;
- break;
- }
+ void computeBoundaryIntersection(const Mesh *mesh, UniformGrid2 &boundaryGrid)
+ {
+ const Array<uint32_t> &boundaryEdges = mesh->boundaryEdges();
+ const uint32_t boundaryEdgeCount = boundaryEdges.size();
+ boundaryGrid.reset(mesh->texcoords(), mesh->indices(), boundaryEdgeCount);
+ for (uint32_t i = 0; i < boundaryEdgeCount; i++)
+ boundaryGrid.append(boundaryEdges[i]);
+ boundaryIntersection = boundaryGrid.intersectSelf(mesh->epsilon());
+#if XA_DEBUG_EXPORT_BOUNDARY_GRID
+ static int exportIndex = 0;
+ char filename[256];
+ XA_SPRINTF(filename, sizeof(filename), "debug_boundary_grid_%03d.tga", exportIndex);
+ boundaryGrid.debugExport(filename);
+ exportIndex++;
+#endif
}
- XA_DEBUG_ASSERT(firstBoundaryEdge != UINT32_MAX);
- for (Mesh::BoundaryEdgeIterator it1(mesh, firstBoundaryEdge); !it1.isDone(); it1.advance()) {
- const uint32_t edge1 = it1.edge();
- for (Mesh::BoundaryEdgeIterator it2(mesh, firstBoundaryEdge); !it2.isDone(); it2.advance()) {
- const uint32_t edge2 = it2.edge();
- // Skip self and edges directly connected to edge1.
- if (edge1 == edge2 || it1.nextEdge() == edge2 || it2.nextEdge() == edge1)
+
+ void computeFlippedFaces(const Mesh *mesh, uint32_t faceCount, Array<uint32_t> *flippedFaces)
+ {
+ totalTriangleCount = flippedTriangleCount = zeroAreaTriangleCount = 0;
+ if (flippedFaces)
+ flippedFaces->clear();
+ for (uint32_t f = 0; f < faceCount; f++) {
+ Vector2 texcoord[3];
+ for (int i = 0; i < 3; i++) {
+ const uint32_t v = mesh->vertexAt(f * 3 + i);
+ texcoord[i] = mesh->texcoord(v);
+ }
+ totalTriangleCount++;
+ const float t1 = texcoord[0].x;
+ const float s1 = texcoord[0].y;
+ const float t2 = texcoord[1].x;
+ const float s2 = texcoord[1].y;
+ const float t3 = texcoord[2].x;
+ const float s3 = texcoord[2].y;
+ const float parametricArea = ((s2 - s1) * (t3 - t1) - (s3 - s1) * (t2 - t1)) * 0.5f;
+ if (isZero(parametricArea, kAreaEpsilon)) {
+ zeroAreaTriangleCount++;
continue;
- const Vector2 &a1 = mesh->texcoord(mesh->vertexAt(meshEdgeIndex0(edge1)));
- const Vector2 &a2 = mesh->texcoord(mesh->vertexAt(meshEdgeIndex1(edge1)));
- const Vector2 &b1 = mesh->texcoord(mesh->vertexAt(meshEdgeIndex0(edge2)));
- const Vector2 &b2 = mesh->texcoord(mesh->vertexAt(meshEdgeIndex1(edge2)));
- if (linesIntersect(a1, a2, b1, b2, mesh->epsilon())) {
- quality.boundaryIntersection = true;
- break;
+ }
+ if (parametricArea < 0.0f) {
+ // Count flipped triangles.
+ flippedTriangleCount++;
+ if (flippedFaces)
+ flippedFaces->push_back(f);
}
}
- if (quality.boundaryIntersection)
- break;
- }
- if (flippedFaces)
- flippedFaces->clear();
- for (uint32_t f = 0; f < faceCount; f++) {
- Vector3 pos[3];
- Vector2 texcoord[3];
- for (int i = 0; i < 3; i++) {
- const uint32_t v = mesh->vertexAt(f * 3 + i);
- pos[i] = mesh->position(v);
- texcoord[i] = mesh->texcoord(v);
- }
- quality.totalTriangleCount++;
- // Evaluate texture stretch metric. See:
- // - "Texture Mapping Progressive Meshes", Sander, Snyder, Gortler & Hoppe
- // - "Mesh Parameterization: Theory and Practice", Siggraph'07 Course Notes, Hormann, Levy & Sheffer.
- const float t1 = texcoord[0].x;
- const float s1 = texcoord[0].y;
- const float t2 = texcoord[1].x;
- const float s2 = texcoord[1].y;
- const float t3 = texcoord[2].x;
- const float s3 = texcoord[2].y;
- float parametricArea = ((s2 - s1) * (t3 - t1) - (s3 - s1) * (t2 - t1)) / 2;
- if (isZero(parametricArea, kAreaEpsilon)) {
- quality.zeroAreaTriangleCount++;
- continue;
- }
- if (parametricArea < 0.0f) {
- // Count flipped triangles.
- quality.flippedTriangleCount++;
+ if (flippedTriangleCount + zeroAreaTriangleCount == totalTriangleCount) {
+ // If all triangles are flipped, then none are.
if (flippedFaces)
- flippedFaces->push_back(f);
- parametricArea = fabsf(parametricArea);
+ flippedFaces->clear();
+ flippedTriangleCount = 0;
}
- const float geometricArea = length(cross(pos[1] - pos[0], pos[2] - pos[0])) / 2;
- const Vector3 Ss = (pos[0] * (t2 - t3) + pos[1] * (t3 - t1) + pos[2] * (t1 - t2)) / (2 * parametricArea);
- const Vector3 St = (pos[0] * (s3 - s2) + pos[1] * (s1 - s3) + pos[2] * (s2 - s1)) / (2 * parametricArea);
- const float a = dot(Ss, Ss); // E
- const float b = dot(Ss, St); // F
- const float c = dot(St, St); // G
- // Compute eigen-values of the first fundamental form:
- const float sigma1 = sqrtf(0.5f * max(0.0f, a + c - sqrtf(square(a - c) + 4 * square(b)))); // gamma uppercase, min eigenvalue.
- const float sigma2 = sqrtf(0.5f * max(0.0f, a + c + sqrtf(square(a - c) + 4 * square(b)))); // gamma lowercase, max eigenvalue.
- XA_ASSERT(sigma2 > sigma1 || equal(sigma1, sigma2, kEpsilon));
- // isometric: sigma1 = sigma2 = 1
- // conformal: sigma1 / sigma2 = 1
- // authalic: sigma1 * sigma2 = 1
- const float rmsStretch = sqrtf((a + c) * 0.5f);
- const float rmsStretch2 = sqrtf((square(sigma1) + square(sigma2)) * 0.5f);
- XA_DEBUG_ASSERT(equal(rmsStretch, rmsStretch2, 0.01f));
- XA_UNUSED(rmsStretch2);
- quality.stretchMetric += square(rmsStretch) * geometricArea;
- quality.maxStretchMetric = max(quality.maxStretchMetric, sigma2);
- if (!isZero(sigma1, 0.000001f)) {
- // sigma1 is zero when geometricArea is zero.
- quality.conformalMetric += (sigma2 / sigma1) * geometricArea;
- }
- quality.authalicMetric += (sigma1 * sigma2) * geometricArea;
- // Accumulate total areas.
- quality.geometricArea += geometricArea;
- quality.parametricArea += parametricArea;
- //triangleConformalEnergy(q, p);
- }
- if (quality.flippedTriangleCount + quality.zeroAreaTriangleCount == quality.totalTriangleCount) {
- // If all triangles are flipped, then none are.
- if (flippedFaces)
- flippedFaces->clear();
- quality.flippedTriangleCount = 0;
- }
- if (quality.flippedTriangleCount > quality.totalTriangleCount / 2)
- {
- // If more than half the triangles are flipped, reverse the flipped / not flipped classification.
- quality.flippedTriangleCount = quality.totalTriangleCount - quality.flippedTriangleCount;
- if (flippedFaces) {
- Array<uint32_t> temp;
- flippedFaces->copyTo(temp);
- flippedFaces->clear();
- for (uint32_t f = 0; f < faceCount; f++) {
- bool match = false;
- for (uint32_t ff = 0; ff < temp.size(); ff++) {
- if (temp[ff] == f) {
- match = true;
- break;
+ if (flippedTriangleCount > totalTriangleCount / 2)
+ {
+ // If more than half the triangles are flipped, reverse the flipped / not flipped classification.
+ flippedTriangleCount = totalTriangleCount - flippedTriangleCount;
+ if (flippedFaces) {
+ Array<uint32_t> temp;
+ flippedFaces->copyTo(temp);
+ flippedFaces->clear();
+ for (uint32_t f = 0; f < faceCount; f++) {
+ bool match = false;
+ for (uint32_t ff = 0; ff < temp.size(); ff++) {
+ if (temp[ff] == f) {
+ match = true;
+ break;
+ }
}
+ if (!match)
+ flippedFaces->push_back(f);
}
- if (!match)
- flippedFaces->push_back(f);
}
}
}
- XA_DEBUG_ASSERT(isFinite(quality.parametricArea) && quality.parametricArea >= 0);
- XA_DEBUG_ASSERT(isFinite(quality.geometricArea) && quality.geometricArea >= 0);
- XA_DEBUG_ASSERT(isFinite(quality.stretchMetric));
- XA_DEBUG_ASSERT(isFinite(quality.maxStretchMetric));
- XA_DEBUG_ASSERT(isFinite(quality.conformalMetric));
- XA_DEBUG_ASSERT(isFinite(quality.authalicMetric));
- if (quality.geometricArea <= 0.0f) {
- quality.stretchMetric = 0.0f;
- quality.maxStretchMetric = 0.0f;
- quality.conformalMetric = 0.0f;
- quality.authalicMetric = 0.0f;
- } else {
- const float normFactor = sqrtf(quality.parametricArea / quality.geometricArea);
- quality.stretchMetric = sqrtf(quality.stretchMetric / quality.geometricArea) * normFactor;
- quality.maxStretchMetric *= normFactor;
- quality.conformalMetric = sqrtf(quality.conformalMetric / quality.geometricArea);
- quality.authalicMetric = sqrtf(quality.authalicMetric / quality.geometricArea);
+
+ void computeMetrics(const Mesh *mesh, uint32_t faceCount)
+ {
+ totalGeometricArea = totalParametricArea = 0.0f;
+ stretchMetric = maxStretchMetric = conformalMetric = authalicMetric = 0.0f;
+ for (uint32_t f = 0; f < faceCount; f++) {
+ Vector3 pos[3];
+ Vector2 texcoord[3];
+ for (int i = 0; i < 3; i++) {
+ const uint32_t v = mesh->vertexAt(f * 3 + i);
+ pos[i] = mesh->position(v);
+ texcoord[i] = mesh->texcoord(v);
+ }
+ // Evaluate texture stretch metric. See:
+ // - "Texture Mapping Progressive Meshes", Sander, Snyder, Gortler & Hoppe
+ // - "Mesh Parameterization: Theory and Practice", Siggraph'07 Course Notes, Hormann, Levy & Sheffer.
+ const float t1 = texcoord[0].x;
+ const float s1 = texcoord[0].y;
+ const float t2 = texcoord[1].x;
+ const float s2 = texcoord[1].y;
+ const float t3 = texcoord[2].x;
+ const float s3 = texcoord[2].y;
+ float parametricArea = ((s2 - s1) * (t3 - t1) - (s3 - s1) * (t2 - t1)) * 0.5f;
+ if (isZero(parametricArea, kAreaEpsilon))
+ continue;
+ if (parametricArea < 0.0f)
+ parametricArea = fabsf(parametricArea);
+ const float geometricArea = length(cross(pos[1] - pos[0], pos[2] - pos[0])) / 2;
+ const Vector3 Ss = (pos[0] * (t2 - t3) + pos[1] * (t3 - t1) + pos[2] * (t1 - t2)) / (2 * parametricArea);
+ const Vector3 St = (pos[0] * (s3 - s2) + pos[1] * (s1 - s3) + pos[2] * (s2 - s1)) / (2 * parametricArea);
+ const float a = dot(Ss, Ss); // E
+ const float b = dot(Ss, St); // F
+ const float c = dot(St, St); // G
+ // Compute eigen-values of the first fundamental form:
+ const float sigma1 = sqrtf(0.5f * max(0.0f, a + c - sqrtf(square(a - c) + 4 * square(b)))); // gamma uppercase, min eigenvalue.
+ const float sigma2 = sqrtf(0.5f * max(0.0f, a + c + sqrtf(square(a - c) + 4 * square(b)))); // gamma lowercase, max eigenvalue.
+ XA_ASSERT(sigma2 > sigma1 || equal(sigma1, sigma2, kEpsilon));
+ // isometric: sigma1 = sigma2 = 1
+ // conformal: sigma1 / sigma2 = 1
+ // authalic: sigma1 * sigma2 = 1
+ const float rmsStretch = sqrtf((a + c) * 0.5f);
+ const float rmsStretch2 = sqrtf((square(sigma1) + square(sigma2)) * 0.5f);
+ XA_DEBUG_ASSERT(equal(rmsStretch, rmsStretch2, 0.01f));
+ XA_UNUSED(rmsStretch2);
+ stretchMetric += square(rmsStretch) * geometricArea;
+ maxStretchMetric = max(maxStretchMetric, sigma2);
+ if (!isZero(sigma1, 0.000001f)) {
+ // sigma1 is zero when geometricArea is zero.
+ conformalMetric += (sigma2 / sigma1) * geometricArea;
+ }
+ authalicMetric += (sigma1 * sigma2) * geometricArea;
+ // Accumulate total areas.
+ totalGeometricArea += geometricArea;
+ totalParametricArea += parametricArea;
+ }
+ XA_DEBUG_ASSERT(isFinite(totalParametricArea) && totalParametricArea >= 0);
+ XA_DEBUG_ASSERT(isFinite(totalGeometricArea) && totalGeometricArea >= 0);
+ XA_DEBUG_ASSERT(isFinite(stretchMetric));
+ XA_DEBUG_ASSERT(isFinite(maxStretchMetric));
+ XA_DEBUG_ASSERT(isFinite(conformalMetric));
+ XA_DEBUG_ASSERT(isFinite(authalicMetric));
+ if (totalGeometricArea > 0.0f) {
+ const float normFactor = sqrtf(totalParametricArea / totalGeometricArea);
+ stretchMetric = sqrtf(stretchMetric / totalGeometricArea) * normFactor;
+ maxStretchMetric *= normFactor;
+ conformalMetric = sqrtf(conformalMetric / totalGeometricArea);
+ authalicMetric = sqrtf(authalicMetric / totalGeometricArea);
+ }
}
- return quality;
-}
+};
struct ChartWarningFlags
{
@@ -5706,24 +6629,30 @@ struct ChartWarningFlags
};
};
+struct ChartCtorBuffers
+{
+ Array<uint32_t> chartMeshIndices;
+ Array<uint32_t> unifiedMeshIndices;
+ Array<uint32_t> boundaryLoops;
+};
+
/// A chart is a connected set of faces with a certain topology (usually a disk).
class Chart
{
public:
- Chart(const segment::Atlas *atlas, const Mesh *originalMesh, uint32_t chartIndex, uint32_t meshId, uint32_t chartGroupId, uint32_t chartId) : m_mesh(nullptr), m_unifiedMesh(nullptr), m_isDisk(false), m_isOrtho(false), m_isPlanar(false), m_warningFlags(0), m_closedHolesCount(0), m_fixedTJunctionsCount(0)
+ Chart(ChartCtorBuffers &buffers, const Basis &basis, ConstArrayView<uint32_t> faces, const Mesh *originalMesh, uint32_t meshId, uint32_t chartGroupId, uint32_t chartId) : m_basis(basis), m_mesh(nullptr), m_unifiedMesh(nullptr), m_unmodifiedUnifiedMesh(nullptr), m_type(ChartType::LSCM), m_warningFlags(0), m_closedHolesCount(0), m_fixedTJunctionsCount(0)
{
XA_UNUSED(meshId);
XA_UNUSED(chartGroupId);
XA_UNUSED(chartId);
- m_basis = atlas->chartBasis(chartIndex);
- atlas->chartFaces(chartIndex).copyTo(m_faceArray);
+ m_faceArray.copyFrom(faces.data, faces.length);
// Copy face indices.
m_mesh = XA_NEW_ARGS(MemTag::Mesh, Mesh, originalMesh->epsilon(), m_faceArray.size() * 3, m_faceArray.size());
m_unifiedMesh = XA_NEW_ARGS(MemTag::Mesh, Mesh, originalMesh->epsilon(), m_faceArray.size() * 3, m_faceArray.size());
- Array<uint32_t> chartMeshIndices;
+ Array<uint32_t> &chartMeshIndices = buffers.chartMeshIndices;
chartMeshIndices.resize(originalMesh->vertexCount());
chartMeshIndices.setAll(UINT32_MAX);
- Array<uint32_t> unifiedMeshIndices;
+ Array<uint32_t> &unifiedMeshIndices = buffers.unifiedMeshIndices;
unifiedMeshIndices.resize(originalMesh->vertexCount());
unifiedMeshIndices.setAll(UINT32_MAX);
// Add vertices.
@@ -5735,11 +6664,7 @@ public:
if (unifiedMeshIndices[unifiedVertex] == (uint32_t)~0) {
unifiedMeshIndices[unifiedVertex] = m_unifiedMesh->vertexCount();
XA_DEBUG_ASSERT(equal(originalMesh->position(vertex), originalMesh->position(unifiedVertex), originalMesh->epsilon()));
-#if XA_SKIP_PARAMETERIZATION
- m_unifiedMesh->addVertex(originalMesh->position(vertex), Vector3(0.0f), atlas->faceTexcoords(m_faceArray[f])[i]);
-#else
m_unifiedMesh->addVertex(originalMesh->position(vertex));
-#endif
}
if (chartMeshIndices[vertex] == (uint32_t)~0) {
chartMeshIndices[vertex] = m_mesh->vertexCount();
@@ -5774,11 +6699,10 @@ public:
}
m_mesh->createBoundaries(); // For AtlasPacker::computeBoundingBox
m_unifiedMesh->createBoundaries();
- m_unifiedMesh->linkBoundaries();
- m_isPlanar = meshIsPlanar(*m_unifiedMesh);
- if (m_isPlanar) {
- m_isDisk = true;
- } else {
+ if (meshIsPlanar(*m_unifiedMesh))
+ m_type = ChartType::Planar;
+ else {
+ m_unifiedMesh->linkBoundaries();
#if XA_DEBUG_EXPORT_OBJ_BEFORE_FIX_TJUNCTION
m_unifiedMesh->writeObjFile("debug_before_fix_tjunction.obj");
#endif
@@ -5791,15 +6715,14 @@ public:
m_warningFlags |= ChartWarningFlags::FixTJunctionsDuplicatedEdge;
if (failed)
m_warningFlags |= ChartWarningFlags::FixTJunctionsFailed;
- m_unifiedMesh->~Mesh();
- XA_FREE(m_unifiedMesh);
+ m_unmodifiedUnifiedMesh = m_unifiedMesh;
m_unifiedMesh = fixedUnifiedMesh;
m_unifiedMesh->createBoundaries();
m_unifiedMesh->linkBoundaries();
m_initialFaceCount = m_unifiedMesh->faceCount(); // Fixing t-junctions rewrites faces.
}
// See if there are any holes that need closing.
- Array<uint32_t> boundaryLoops;
+ Array<uint32_t> &boundaryLoops = buffers.boundaryLoops;
meshGetBoundaryLoops(*m_unifiedMesh, boundaryLoops);
if (boundaryLoops.size() > 1) {
#if XA_DEBUG_EXPORT_OBJ_CLOSE_HOLES_ERROR
@@ -5810,16 +6733,21 @@ public:
// - Find cuts that reduce genus.
// - Find cuts to connect holes.
// - Use minimal spanning trees or seamster.
- Array<uint32_t> holeFaceCounts;
XA_PROFILE_START(closeChartMeshHoles)
- failed = !meshCloseHoles(m_unifiedMesh, boundaryLoops, m_basis.normal, holeFaceCounts);
+ uint32_t holeCount = 0;
+#if XA_DEBUG_EXPORT_OBJ_CLOSE_HOLES_ERROR
+ Array<uint32_t> holeFaceCounts;
+ failed = !meshCloseHoles(m_unifiedMesh, boundaryLoops, m_basis.normal, &holeFaceCounts);
+#else
+ failed = !meshCloseHoles(m_unifiedMesh, boundaryLoops, m_basis.normal, &holeCount, nullptr);
+#endif
XA_PROFILE_END(closeChartMeshHoles)
m_unifiedMesh->createBoundaries();
m_unifiedMesh->linkBoundaries();
meshGetBoundaryLoops(*m_unifiedMesh, boundaryLoops);
if (failed || boundaryLoops.size() > 1)
m_warningFlags |= ChartWarningFlags::CloseHolesFailed;
- m_closedHolesCount = holeFaceCounts.size();
+ m_closedHolesCount = holeCount;
#if XA_DEBUG_EXPORT_OBJ_CLOSE_HOLES_ERROR
if (m_warningFlags & ChartWarningFlags::CloseHolesFailed) {
char filename[256];
@@ -5848,18 +6776,75 @@ public:
}
#endif
}
- // Note: MeshTopology needs linked boundaries.
- MeshTopology topology(m_unifiedMesh);
- m_isDisk = topology.isDisk();
-#if XA_DEBUG_EXPORT_OBJ_NOT_DISK
- if (!m_isDisk) {
- char filename[256];
- XA_SPRINTF(filename, sizeof(filename), "debug_mesh_%03u_chartgroup_%03u_chart_%03u_not_disk.obj", meshId, chartGroupId, chartId);
- m_unifiedMesh->writeObjFile(filename);
+ }
+ }
+
+#if XA_RECOMPUTE_CHARTS
+ Chart(ChartCtorBuffers &buffers, const Chart *parent, const Mesh *parentMesh, ConstArrayView<uint32_t> faces, const Vector2 *texcoords, const Mesh *originalMesh, uint32_t meshId, uint32_t chartGroupId, uint32_t chartId) : m_mesh(nullptr), m_unifiedMesh(nullptr), m_unmodifiedUnifiedMesh(nullptr), m_type(ChartType::Piecewise), m_warningFlags(0), m_closedHolesCount(0), m_fixedTJunctionsCount(0)
+ {
+ XA_UNUSED(meshId);
+ XA_UNUSED(chartGroupId);
+ XA_UNUSED(chartId);
+ const uint32_t faceCount = m_initialFaceCount = faces.length;
+ m_faceArray.resize(faceCount);
+ for (uint32_t i = 0; i < faceCount; i++)
+ m_faceArray[i] = parent->m_faceArray[faces[i]]; // Map faces to parent chart original mesh.
+ // Copy face indices.
+ m_mesh = XA_NEW_ARGS(MemTag::Mesh, Mesh, originalMesh->epsilon(), m_faceArray.size() * 3, m_faceArray.size());
+ m_unifiedMesh = XA_NEW_ARGS(MemTag::Mesh, Mesh, originalMesh->epsilon(), m_faceArray.size() * 3, m_faceArray.size());
+ Array<uint32_t> &chartMeshIndices = buffers.chartMeshIndices;
+ chartMeshIndices.resize(originalMesh->vertexCount());
+ chartMeshIndices.setAll(UINT32_MAX);
+ Array<uint32_t> &unifiedMeshIndices = buffers.unifiedMeshIndices;
+ unifiedMeshIndices.resize(originalMesh->vertexCount());
+ unifiedMeshIndices.setAll(UINT32_MAX);
+ // Add vertices.
+ for (uint32_t f = 0; f < faceCount; f++) {
+ for (uint32_t i = 0; i < 3; i++) {
+ const uint32_t vertex = originalMesh->vertexAt(m_faceArray[f] * 3 + i);
+ const uint32_t unifiedVertex = originalMesh->firstColocal(vertex);
+ const uint32_t parentVertex = parentMesh->vertexAt(faces[f] * 3 + i);
+ if (unifiedMeshIndices[unifiedVertex] == (uint32_t)~0) {
+ unifiedMeshIndices[unifiedVertex] = m_unifiedMesh->vertexCount();
+ XA_DEBUG_ASSERT(equal(originalMesh->position(vertex), originalMesh->position(unifiedVertex), originalMesh->epsilon()));
+ m_unifiedMesh->addVertex(originalMesh->position(vertex), Vector3(0.0f), texcoords[parentVertex]);
+ }
+ if (chartMeshIndices[vertex] == (uint32_t)~0) {
+ chartMeshIndices[vertex] = m_mesh->vertexCount();
+ m_chartToOriginalMap.push_back(vertex);
+ m_chartToUnifiedMap.push_back(unifiedMeshIndices[unifiedVertex]);
+ m_mesh->addVertex(originalMesh->position(vertex), Vector3(0.0f), texcoords[parentVertex]);
+ }
+ }
+ }
+ // Add faces.
+ for (uint32_t f = 0; f < faceCount; f++) {
+ uint32_t indices[3], unifiedIndices[3];
+ for (uint32_t i = 0; i < 3; i++) {
+ const uint32_t vertex = originalMesh->vertexAt(m_faceArray[f] * 3 + i);
+ indices[i] = chartMeshIndices[vertex];
+ unifiedIndices[i] = unifiedMeshIndices[originalMesh->firstColocal(vertex)];
+ }
+ Mesh::AddFaceResult::Enum result = m_mesh->addFace(indices);
+ XA_UNUSED(result);
+ XA_DEBUG_ASSERT(result == Mesh::AddFaceResult::OK);
+#if XA_DEBUG
+ // Unifying colocals may create degenerate edges. e.g. if two triangle vertices are colocal.
+ for (int i = 0; i < 3; i++) {
+ const uint32_t index1 = unifiedIndices[i];
+ const uint32_t index2 = unifiedIndices[(i + 1) % 3];
+ XA_DEBUG_ASSERT(index1 != index2);
}
#endif
+ result = m_unifiedMesh->addFace(unifiedIndices);
+ XA_UNUSED(result);
+ XA_DEBUG_ASSERT(result == Mesh::AddFaceResult::OK);
}
+ m_mesh->createBoundaries(); // For AtlasPacker::computeBoundingBox
+ m_unifiedMesh->createBoundaries();
+ m_unifiedMesh->linkBoundaries();
}
+#endif
~Chart()
{
@@ -5871,16 +6856,19 @@ public:
m_unifiedMesh->~Mesh();
XA_FREE(m_unifiedMesh);
}
+ if (m_unmodifiedUnifiedMesh) {
+ m_unmodifiedUnifiedMesh->~Mesh();
+ XA_FREE(m_unmodifiedUnifiedMesh);
+ }
}
const Basis &basis() const { return m_basis; }
- bool isDisk() const { return m_isDisk; }
- bool isOrtho() const { return m_isOrtho; }
- bool isPlanar() const { return m_isPlanar; }
+ ChartType::Enum type() const { return m_type; }
uint32_t warningFlags() const { return m_warningFlags; }
uint32_t closedHolesCount() const { return m_closedHolesCount; }
uint32_t fixedTJunctionsCount() const { return m_fixedTJunctionsCount; }
- const ParameterizationQuality &paramQuality() const { return m_paramQuality; }
+ const Quality &quality() const { return m_quality; }
+ uint32_t initialFaceCount() const { return m_initialFaceCount; }
#if XA_DEBUG_EXPORT_OBJ_INVALID_PARAMETERIZATION
const Array<uint32_t> &paramFlippedFaces() const { return m_paramFlippedFaces; }
#endif
@@ -5889,26 +6877,31 @@ public:
Mesh *mesh() { return m_mesh; }
const Mesh *unifiedMesh() const { return m_unifiedMesh; }
Mesh *unifiedMesh() { return m_unifiedMesh; }
+ const Mesh *unmodifiedUnifiedMesh() const { return m_unmodifiedUnifiedMesh; }
uint32_t mapChartVertexToOriginalVertex(uint32_t i) const { return m_chartToOriginalMap[i]; }
- void evaluateOrthoParameterizationQuality()
+ void evaluateOrthoQuality(UniformGrid2 &boundaryGrid)
{
XA_PROFILE_START(parameterizeChartsEvaluateQuality)
- m_paramQuality = calculateParameterizationQuality(m_unifiedMesh, m_initialFaceCount, nullptr);
+ m_quality.computeBoundaryIntersection(m_unifiedMesh, boundaryGrid);
+ m_quality.computeFlippedFaces(m_unifiedMesh, m_initialFaceCount, nullptr);
+ m_quality.computeMetrics(m_unifiedMesh, m_initialFaceCount);
XA_PROFILE_END(parameterizeChartsEvaluateQuality)
// Use orthogonal parameterization if quality is acceptable.
- if (!m_paramQuality.boundaryIntersection && m_paramQuality.geometricArea > 0.0f && m_paramQuality.stretchMetric <= 1.1f && m_paramQuality.maxStretchMetric <= 1.25f)
- m_isOrtho = true;
+ if (!m_quality.boundaryIntersection && m_quality.totalGeometricArea > 0.0f && m_quality.stretchMetric <= 1.1f && m_quality.maxStretchMetric <= 1.25f)
+ m_type = ChartType::Ortho;
}
- void evaluateParameterizationQuality()
+ void evaluateQuality(UniformGrid2 &boundaryGrid)
{
XA_PROFILE_START(parameterizeChartsEvaluateQuality)
+ m_quality.computeBoundaryIntersection(m_unifiedMesh, boundaryGrid);
#if XA_DEBUG_EXPORT_OBJ_INVALID_PARAMETERIZATION
- m_paramQuality = calculateParameterizationQuality(m_unifiedMesh, m_initialFaceCount, &m_paramFlippedFaces);
+ m_quality.computeFlippedFaces(m_unifiedMesh, m_initialFaceCount, &m_paramFlippedFaces);
#else
- m_paramQuality = calculateParameterizationQuality(m_unifiedMesh, m_initialFaceCount, nullptr);
+ m_quality.computeFlippedFaces(m_unifiedMesh, m_initialFaceCount, nullptr);
#endif
+ // Don't need to call computeMetrics here, that's only used in evaluateOrthoQuality to determine if quality is acceptable enough to use ortho projection.
XA_PROFILE_END(parameterizeChartsEvaluateQuality)
}
@@ -5920,16 +6913,6 @@ public:
m_mesh->texcoord(v) = m_unifiedMesh->texcoord(m_chartToUnifiedMap[v]);
}
- float computeSurfaceArea() const
- {
- return m_mesh->computeSurfaceArea();
- }
-
- float computeParametricArea() const
- {
- return m_mesh->computeParametricArea();
- }
-
Vector2 computeParametricBounds() const
{
Vector2 minCorner(FLT_MAX, FLT_MAX);
@@ -5946,7 +6929,8 @@ private:
Basis m_basis;
Mesh *m_mesh;
Mesh *m_unifiedMesh;
- bool m_isDisk, m_isOrtho, m_isPlanar;
+ Mesh *m_unmodifiedUnifiedMesh; // Unified mesh before fixing t-junctions. Null if no t-junctions were fixed
+ ChartType::Enum m_type;
uint32_t m_warningFlags;
uint32_t m_initialFaceCount; // Before fixing T-junctions and/or closing holes.
uint32_t m_closedHolesCount, m_fixedTJunctionsCount;
@@ -5959,7 +6943,7 @@ private:
Array<uint32_t> m_chartToUnifiedMap;
- ParameterizationQuality m_paramQuality;
+ Quality m_quality;
#if XA_DEBUG_EXPORT_OBJ_INVALID_PARAMETERIZATION
Array<uint32_t> m_paramFlippedFaces;
#endif
@@ -5967,12 +6951,13 @@ private:
struct CreateChartTaskArgs
{
- const segment::Atlas *atlas;
const Mesh *mesh;
- uint32_t chartIndex; // In the atlas.
+ const Basis *basis;
+ ConstArrayView<uint32_t> faces;
uint32_t meshId;
uint32_t chartGroupId;
uint32_t chartId;
+ ThreadLocal<ChartCtorBuffers> *chartBuffers;
Chart **chart;
};
@@ -5980,7 +6965,7 @@ static void runCreateChartTask(void *userData)
{
XA_PROFILE_START(createChartMeshesThread)
auto args = (CreateChartTaskArgs *)userData;
- *(args->chart) = XA_NEW_ARGS(MemTag::Default, Chart, args->atlas, args->mesh, args->chartIndex, args->meshId, args->chartGroupId, args->chartId);
+ *(args->chart) = XA_NEW_ARGS(MemTag::Default, Chart, args->chartBuffers->get(), *(args->basis), args->faces, args->mesh, args->meshId, args->chartGroupId, args->chartId);
XA_PROFILE_END(createChartMeshesThread)
}
@@ -5988,6 +6973,7 @@ struct ParameterizeChartTaskArgs
{
Chart *chart;
ParameterizeFunc func;
+ ThreadLocal<UniformGrid2> *boundaryGrid;
};
static void runParameterizeChartTask(void *userData)
@@ -5995,24 +6981,26 @@ static void runParameterizeChartTask(void *userData)
auto args = (ParameterizeChartTaskArgs *)userData;
Mesh *mesh = args->chart->unifiedMesh();
XA_PROFILE_START(parameterizeChartsOrthogonal)
-#if 1
- computeOrthogonalProjectionMap(mesh);
-#else
- for (uint32_t i = 0; i < vertexCount; i++)
- mesh->texcoord(i) = Vector2(dot(args->chart->basis().tangent, mesh->position(i)), dot(args->chart->basis().bitangent, mesh->position(i)));
-#endif
+ {
+ // Project vertices to plane.
+ const uint32_t vertexCount = mesh->vertexCount();
+ const Basis &basis = args->chart->basis();
+ for (uint32_t i = 0; i < vertexCount; i++)
+ mesh->texcoord(i) = Vector2(dot(basis.tangent, mesh->position(i)), dot(basis.bitangent, mesh->position(i)));
+ }
XA_PROFILE_END(parameterizeChartsOrthogonal)
- args->chart->evaluateOrthoParameterizationQuality();
- if (!args->chart->isOrtho() && !args->chart->isPlanar()) {
+ // Computing charts checks for flipped triangles and boundary intersection. Don't need to do that again here if chart is planar.
+ if (args->chart->type() != ChartType::Planar)
+ args->chart->evaluateOrthoQuality(args->boundaryGrid->get());
+ if (args->chart->type() == ChartType::LSCM) {
XA_PROFILE_START(parameterizeChartsLSCM)
if (args->func)
args->func(&mesh->position(0).x, &mesh->texcoord(0).x, mesh->vertexCount(), mesh->indices(), mesh->indexCount());
- else if (args->chart->isDisk())
+ else
computeLeastSquaresConformalMap(mesh);
XA_PROFILE_END(parameterizeChartsLSCM)
- args->chart->evaluateParameterizationQuality();
+ args->chart->evaluateQuality(args->boundaryGrid->get());
}
- // @@ Check that parameterization quality is above a certain threshold.
// Transfer parameterization from unified mesh to chart mesh.
args->chart->transferParameterization();
}
@@ -6021,27 +7009,33 @@ static void runParameterizeChartTask(void *userData)
class ChartGroup
{
public:
- ChartGroup(uint32_t id, const Mesh *sourceMesh, uint32_t faceGroup) : m_sourceId(sourceMesh->id()), m_id(id), m_isVertexMap(faceGroup == UINT32_MAX), m_paramAddedChartsCount(0), m_paramDeletedChartsCount(0)
+ ChartGroup(uint32_t id, const Mesh *sourceMesh, uint16_t faceGroup) : m_sourceId(sourceMesh->id()), m_id(id), m_isVertexMap(faceGroup == Mesh::kInvalidFaceGroup), m_paramAddedChartsCount(0), m_paramDeletedChartsCount(0)
{
// Create new mesh from the source mesh, using faces that belong to this group.
const uint32_t sourceFaceCount = sourceMesh->faceCount();
- for (uint32_t f = 0; f < sourceFaceCount; f++) {
- if (sourceMesh->faceGroupAt(f) == faceGroup)
- m_faceToSourceFaceMap.push_back(f);
+ if (!m_isVertexMap) {
+ m_faceToSourceFaceMap.reserve(sourceMesh->faceGroupFaceCount(faceGroup));
+ for (Mesh::GroupFaceIterator it(sourceMesh, faceGroup); !it.isDone(); it.advance())
+ m_faceToSourceFaceMap.push_back(it.face());
+ } else {
+ for (uint32_t f = 0; f < sourceFaceCount; f++) {
+ if (sourceMesh->faceGroupAt(f) == faceGroup)
+ m_faceToSourceFaceMap.push_back(f);
+ }
}
// Only initial meshes have face groups and ignored faces. The only flag we care about is HasNormals.
const uint32_t faceCount = m_faceToSourceFaceMap.size();
- m_mesh = XA_NEW_ARGS(MemTag::Mesh, Mesh, sourceMesh->epsilon(), faceCount * 3, faceCount, sourceMesh->flags() & MeshFlags::HasNormals);
XA_DEBUG_ASSERT(faceCount > 0);
- Array<uint32_t> meshIndices;
- meshIndices.resize(sourceMesh->vertexCount());
- meshIndices.setAll((uint32_t)~0);
+ const uint32_t approxVertexCount = faceCount * 3;
+ m_mesh = XA_NEW_ARGS(MemTag::Mesh, Mesh, sourceMesh->epsilon(), approxVertexCount, faceCount, sourceMesh->flags() & MeshFlags::HasNormals);
+ m_vertexToSourceVertexMap.reserve(approxVertexCount);
+ HashMap<uint32_t> sourceVertexToVertexMap(MemTag::Mesh, approxVertexCount);
for (uint32_t f = 0; f < faceCount; f++) {
const uint32_t face = m_faceToSourceFaceMap[f];
for (uint32_t i = 0; i < 3; i++) {
const uint32_t vertex = sourceMesh->vertexAt(face * 3 + i);
- if (meshIndices[vertex] == (uint32_t)~0) {
- meshIndices[vertex] = m_mesh->vertexCount();
+ if (sourceVertexToVertexMap.get(vertex) == UINT32_MAX) {
+ sourceVertexToVertexMap.add(vertex);
m_vertexToSourceVertexMap.push_back(vertex);
Vector3 normal(0.0f);
if (sourceMesh->flags() & MeshFlags::HasNormals)
@@ -6056,8 +7050,8 @@ public:
uint32_t indices[3];
for (uint32_t i = 0; i < 3; i++) {
const uint32_t vertex = sourceMesh->vertexAt(face * 3 + i);
- XA_DEBUG_ASSERT(meshIndices[vertex] != (uint32_t)~0);
- indices[i] = meshIndices[vertex];
+ indices[i] = sourceVertexToVertexMap.get(vertex);
+ XA_DEBUG_ASSERT(indices[i] != UINT32_MAX);
}
// Don't copy flags, it doesn't matter if a face is ignored after this point. All ignored faces get their own vertex map (m_isVertexMap) ChartGroup.
// Don't hash edges if m_isVertexMap, they may be degenerate.
@@ -6068,7 +7062,6 @@ public:
if (!m_isVertexMap) {
m_mesh->createColocals();
m_mesh->createBoundaries();
- m_mesh->linkBoundaries();
}
#if XA_DEBUG_EXPORT_OBJ_CHART_GROUPS
char filename[256];
@@ -6083,14 +7076,14 @@ public:
{
m_mesh->~Mesh();
XA_FREE(m_mesh);
- for (uint32_t i = 0; i < m_chartArray.size(); i++) {
- m_chartArray[i]->~Chart();
- XA_FREE(m_chartArray[i]);
+ for (uint32_t i = 0; i < m_charts.size(); i++) {
+ m_charts[i]->~Chart();
+ XA_FREE(m_charts[i]);
}
}
- uint32_t chartCount() const { return m_chartArray.size(); }
- Chart *chartAt(uint32_t i) const { return m_chartArray[i]; }
+ uint32_t chartCount() const { return m_charts.size(); }
+ Chart *chartAt(uint32_t i) const { return m_charts[i]; }
uint32_t paramAddedChartsCount() const { return m_paramAddedChartsCount; }
uint32_t paramDeletedChartsCount() const { return m_paramDeletedChartsCount; }
bool isVertexMap() const { return m_isVertexMap; }
@@ -6158,40 +7151,41 @@ public:
- emphasize roundness metrics to prevent those cases.
- If interior self-overlaps: preserve boundary parameterization and use mean-value map.
*/
- void computeCharts(TaskScheduler *taskScheduler, const ChartOptions &options)
+ void computeCharts(TaskScheduler *taskScheduler, const ChartOptions &options, segment::Atlas &atlas, ThreadLocal<ChartCtorBuffers> *chartBuffers)
{
m_chartOptions = options;
// This function may be called multiple times, so destroy existing charts.
- for (uint32_t i = 0; i < m_chartArray.size(); i++) {
- m_chartArray[i]->~Chart();
- XA_FREE(m_chartArray[i]);
+ for (uint32_t i = 0; i < m_charts.size(); i++) {
+ m_charts[i]->~Chart();
+ XA_FREE(m_charts[i]);
}
- m_chartArray.clear();
+ m_charts.clear();
#if XA_DEBUG_SINGLE_CHART
Array<uint32_t> chartFaces;
chartFaces.resize(m_mesh->faceCount());
for (uint32_t i = 0; i < chartFaces.size(); i++)
chartFaces[i] = i;
Chart *chart = XA_NEW_ARGS(MemTag::Default, Chart, m_mesh, chartFaces, m_sourceId, m_id, 0);
- m_chartArray.push_back(chart);
+ m_charts.push_back(chart);
#else
XA_PROFILE_START(buildAtlas)
- segment::Atlas atlas(m_mesh, nullptr, options);
+ atlas.reset(m_sourceId, m_id, m_mesh, options);
buildAtlas(atlas, options);
XA_PROFILE_END(buildAtlas)
const uint32_t chartCount = atlas.chartCount();
- m_chartArray.resize(chartCount);
+ m_charts.resize(chartCount);
Array<CreateChartTaskArgs> taskArgs;
taskArgs.resize(chartCount);
for (uint32_t i = 0; i < chartCount; i++) {
CreateChartTaskArgs &args = taskArgs[i];
- args.atlas = &atlas;
+ args.basis = &atlas.chartBasis(i);
+ args.faces = atlas.chartFaces(i);
args.mesh = m_mesh;
- args.chartIndex = i;
args.meshId = m_sourceId;
args.chartGroupId = m_id;
args.chartId = i;
- args.chart = &m_chartArray[i];
+ args.chartBuffers = chartBuffers;
+ args.chart = &m_charts[i];
}
XA_PROFILE_START(createChartMeshesReal)
TaskGroupHandle taskGroup = taskScheduler->createTaskGroup(chartCount);
@@ -6225,26 +7219,22 @@ public:
#endif
}
- void parameterizeCharts(TaskScheduler *taskScheduler, ParameterizeFunc func)
- {
- const uint32_t chartCount = m_chartArray.size();
-#if XA_SKIP_PARAMETERIZATION
- XA_UNUSED(taskScheduler);
- XA_UNUSED(func);
- for (uint32_t i = 0; i < chartCount; i++) {
- Chart *chart = m_chartArray[i];
- chart->evaluateOrthoParameterizationQuality();
- chart->evaluateParameterizationQuality();
- chart->transferParameterization();
- }
+#if XA_RECOMPUTE_CHARTS
+ void parameterizeCharts(TaskScheduler *taskScheduler, ParameterizeFunc func, ThreadLocal<UniformGrid2> *boundaryGrid, ThreadLocal<ChartCtorBuffers> *chartBuffers, ThreadLocal<PiecewiseParam> *piecewiseParam)
#else
+ void parameterizeCharts(TaskScheduler* taskScheduler, ParameterizeFunc func, ThreadLocal<UniformGrid2>* boundaryGrid, ThreadLocal<ChartCtorBuffers>* /*chartBuffers*/)
+#endif
+ {
+ m_paramAddedChartsCount = 0;
+ const uint32_t chartCount = m_charts.size();
Array<ParameterizeChartTaskArgs> taskArgs;
taskArgs.resize(chartCount);
TaskGroupHandle taskGroup = taskScheduler->createTaskGroup(chartCount);
for (uint32_t i = 0; i < chartCount; i++) {
ParameterizeChartTaskArgs &args = taskArgs[i];
- args.chart = m_chartArray[i];
+ args.chart = m_charts[i];
args.func = func;
+ args.boundaryGrid = boundaryGrid;
Task task;
task.userData = &args;
task.func = runParameterizeChartTask;
@@ -6255,67 +7245,65 @@ public:
// Find charts with invalid parameterizations.
Array<Chart *> invalidCharts;
for (uint32_t i = 0; i < chartCount; i++) {
- Chart *chart = m_chartArray[i];
- const ParameterizationQuality &quality = chart->paramQuality();
+ Chart *chart = m_charts[i];
+ const Quality &quality = chart->quality();
if (quality.boundaryIntersection || quality.flippedTriangleCount > 0)
invalidCharts.push_back(chart);
}
if (invalidCharts.isEmpty())
return;
// Recompute charts with invalid parameterizations.
- Array<uint32_t> meshFaces;
+ PiecewiseParam &pp = piecewiseParam->get();
for (uint32_t i = 0; i < invalidCharts.size(); i++) {
Chart *invalidChart = invalidCharts[i];
- const Mesh *invalidMesh = invalidChart->mesh();
- const uint32_t faceCount = invalidMesh->faceCount();
- meshFaces.resize(faceCount);
- float invalidChartArea = 0.0f;
- for (uint32_t j = 0; j < faceCount; j++) {
- meshFaces[j] = invalidChart->mapFaceToSourceFace(j);
- invalidChartArea += invalidMesh->faceArea(j);
- }
- ChartOptions options = m_chartOptions;
- options.maxChartArea = invalidChartArea * 0.2f;
- options.maxThreshold = 0.25f;
- options.maxIterations = 3;
- segment::Atlas atlas(m_mesh, &meshFaces, options);
- buildAtlas(atlas, options);
- for (uint32_t j = 0; j < atlas.chartCount(); j++) {
- Chart *chart = XA_NEW_ARGS(MemTag::Default, Chart, &atlas, m_mesh, j, m_sourceId, m_id, m_chartArray.size());
- m_chartArray.push_back(chart);
- m_paramAddedChartsCount++;
+ // Fixing t-junctions rewrites unified mesh faces, and we need to map faces back to input mesh. So use the unmodified unified mesh.
+ const Mesh *invalidMesh = invalidChart->unmodifiedUnifiedMesh();
+ uint32_t faceCount = 0;
+ if (invalidMesh) {
+ faceCount = invalidMesh->faceCount();
+ } else {
+ invalidMesh = invalidChart->unifiedMesh();
+ faceCount = invalidChart->initialFaceCount(); // Not invalidMesh->faceCount(). Don't want faces added by hole closing.
}
+ pp.reset(invalidMesh, faceCount);
#if XA_DEBUG_EXPORT_OBJ_RECOMPUTED_CHARTS
char filename[256];
- XA_SPRINTF(filename, sizeof(filename), "debug_mesh_%03u_chartgroup_%03u_recomputed_chart_%u.obj", m_sourceId, m_id, i);
+ XA_SPRINTF(filename, sizeof(filename), "debug_mesh_%03u_chartgroup_%03u_recomputed_chart_%03u.obj", m_sourceId, m_id, m_paramAddedChartsCount);
FILE *file;
XA_FOPEN(file, filename, "w");
- if (file) {
- m_mesh->writeObjVertices(file);
- for (uint32_t j = 0; j < builder.chartCount(); j++) {
- fprintf(file, "o chart_%04d\n", j);
+ uint32_t subChartIndex = 0;
+#endif
+ for (;;) {
+ if (!pp.computeChart())
+ break;
+ Chart *chart = XA_NEW_ARGS(MemTag::Default, Chart, chartBuffers->get(), invalidChart, invalidMesh, pp.chartFaces(), pp.texcoords(), m_mesh, m_sourceId, m_id, m_charts.size());
+ m_charts.push_back(chart);
+#if XA_DEBUG_EXPORT_OBJ_RECOMPUTED_CHARTS
+ if (file) {
+ for (uint32_t j = 0; j < invalidMesh->vertexCount(); j++) {
+ fprintf(file, "v %g %g %g\n", invalidMesh->position(j).x, invalidMesh->position(j).y, invalidMesh->position(j).z);
+ fprintf(file, "vt %g %g\n", pp.texcoords()[j].x, pp.texcoords()[j].y);
+ }
+ fprintf(file, "o chart%03u\n", subChartIndex);
fprintf(file, "s off\n");
- const Array<uint32_t> &faces = builder.chartFaces(j);
- for (uint32_t f = 0; f < faces.size(); f++)
- m_mesh->writeObjFace(file, faces[f]);
+ for (uint32_t f = 0; f < pp.chartFaces().length; f++) {
+ fprintf(file, "f ");
+ const uint32_t face = pp.chartFaces()[f];
+ for (uint32_t j = 0; j < 3; j++) {
+ const uint32_t index = invalidMesh->vertexCount() * subChartIndex + invalidMesh->vertexAt(face * 3 + j) + 1; // 1-indexed
+ fprintf(file, "%d/%d/%c", index, index, j == 2 ? '\n' : ' ');
+ }
+ }
}
- fclose(file);
+ subChartIndex++;
+#endif
+ m_paramAddedChartsCount++;
}
+#if XA_DEBUG_EXPORT_OBJ_RECOMPUTED_CHARTS
+ if (file)
+ fclose(file);
#endif
}
- // Parameterize the new charts.
- taskGroup = taskScheduler->createTaskGroup(m_chartArray.size() - chartCount);
- taskArgs.resize(m_chartArray.size() - chartCount);
- for (uint32_t i = chartCount; i < m_chartArray.size(); i++) {
- ParameterizeChartTaskArgs &args = taskArgs[i - chartCount];
- args.chart = m_chartArray[i];
- args.func = func;
- Task task;
- task.userData = &args;
- task.func = runParameterizeChartTask;
- taskScheduler->run(taskGroup, task);
- }
- taskScheduler->wait(&taskGroup);
// Remove and delete the invalid charts.
for (uint32_t i = 0; i < invalidCharts.size(); i++) {
Chart *chart = invalidCharts[i];
@@ -6325,7 +7313,6 @@ public:
m_paramDeletedChartsCount++;
}
#endif // XA_RECOMPUTE_CHARTS
-#endif // XA_SKIP_PARAMETERIZATION
}
private:
@@ -6343,19 +7330,18 @@ private:
atlas.resetCharts();
// Restart process growing charts in parallel.
uint32_t iteration = 0;
- while (true) {
- if (!atlas.growCharts(options.maxThreshold)) {
- // If charts cannot grow more: fill holes, merge charts, relocate seeds and start new iteration.
- atlas.fillHoles(options.maxThreshold * 0.5f);
+ for (;;) {
+ atlas.growCharts(options.maxThreshold);
+ // When charts cannot grow more: fill holes, merge charts, relocate seeds and start new iteration.
+ atlas.fillHoles(options.maxThreshold * 0.5f);
#if XA_MERGE_CHARTS
- atlas.mergeCharts();
+ atlas.mergeCharts();
#endif
- if (++iteration == options.maxIterations)
- break;
- if (!atlas.relocateSeeds())
- break;
- atlas.resetCharts();
- }
+ if (++iteration == options.maxIterations)
+ break;
+ if (!atlas.relocateSeeds())
+ break;
+ atlas.resetCharts();
}
// Make sure no holes are left!
XA_DEBUG_ASSERT(atlas.facesLeft() == 0);
@@ -6363,9 +7349,9 @@ private:
void removeChart(const Chart *chart)
{
- for (uint32_t i = 0; i < m_chartArray.size(); i++) {
- if (m_chartArray[i] == chart) {
- m_chartArray.removeAt(i);
+ for (uint32_t i = 0; i < m_charts.size(); i++) {
+ if (m_charts[i] == chart) {
+ m_charts.removeAt(i);
return;
}
}
@@ -6376,7 +7362,7 @@ private:
Mesh *m_mesh;
Array<uint32_t> m_faceToSourceFaceMap; // List of faces of the source mesh that belong to this chart group.
Array<uint32_t> m_vertexToSourceVertexMap; // Map vertices of the mesh to vertices of the source mesh.
- Array<Chart *> m_chartArray;
+ Array<Chart *> m_charts;
ChartOptions m_chartOptions;
uint32_t m_paramAddedChartsCount; // Number of new charts added by recomputing charts with invalid parameterizations.
uint32_t m_paramDeletedChartsCount; // Number of charts with invalid parameterizations that were deleted, after charts were recomputed.
@@ -6384,7 +7370,7 @@ private:
struct CreateChartGroupTaskArgs
{
- uint32_t faceGroup;
+ uint16_t faceGroup;
uint32_t groupId;
const Mesh *mesh;
ChartGroup **chartGroup;
@@ -6402,6 +7388,8 @@ struct ComputeChartsTaskArgs
{
TaskScheduler *taskScheduler;
ChartGroup *chartGroup;
+ ThreadLocal<segment::Atlas> *atlas;
+ ThreadLocal<ChartCtorBuffers> *chartBuffers;
const ChartOptions *options;
Progress *progress;
};
@@ -6412,7 +7400,7 @@ static void runComputeChartsJob(void *userData)
if (args->progress->cancel)
return;
XA_PROFILE_START(computeChartsThread)
- args->chartGroup->computeCharts(args->taskScheduler, *args->options);
+ args->chartGroup->computeCharts(args->taskScheduler, *args->options, args->atlas->get(), args->chartBuffers);
XA_PROFILE_END(computeChartsThread)
args->progress->value++;
args->progress->update();
@@ -6423,6 +7411,11 @@ struct ParameterizeChartsTaskArgs
TaskScheduler *taskScheduler;
ChartGroup *chartGroup;
ParameterizeFunc func;
+ ThreadLocal<UniformGrid2> *boundaryGrid;
+ ThreadLocal<ChartCtorBuffers> *chartBuffers;
+#if XA_RECOMPUTE_CHARTS
+ ThreadLocal<PiecewiseParam> *piecewiseParam;
+#endif
Progress *progress;
};
@@ -6432,7 +7425,11 @@ static void runParameterizeChartsJob(void *userData)
if (args->progress->cancel)
return;
XA_PROFILE_START(parameterizeChartsThread)
- args->chartGroup->parameterizeCharts(args->taskScheduler, args->func);
+#if XA_RECOMPUTE_CHARTS
+ args->chartGroup->parameterizeCharts(args->taskScheduler, args->func, args->boundaryGrid, args->chartBuffers, args->piecewiseParam);
+#else
+ args->chartGroup->parameterizeCharts(args->taskScheduler, args->func, args->boundaryGrid, args->chartBuffers);
+#endif
XA_PROFILE_END(parameterizeChartsThread)
args->progress->value++;
args->progress->update();
@@ -6482,31 +7479,17 @@ public:
// This function is thread safe.
void addMesh(TaskScheduler *taskScheduler, const Mesh *mesh)
{
- // Get list of face groups.
- const uint32_t faceCount = mesh->faceCount();
- Array<uint32_t> faceGroups;
- for (uint32_t f = 0; f < faceCount; f++) {
- const uint32_t group = mesh->faceGroupAt(f);
- bool exists = false;
- for (uint32_t g = 0; g < faceGroups.size(); g++) {
- if (faceGroups[g] == group) {
- exists = true;
- break;
- }
- }
- if (!exists)
- faceGroups.push_back(group);
- }
// Create one chart group per face group.
+ // If there's any ignored faces in the mesh, create an extra face group for that (vertex map).
// Chart group creation is slow since it copies a chunk of the source mesh, so use tasks.
Array<ChartGroup *> chartGroups;
- chartGroups.resize(faceGroups.size());
+ chartGroups.resize(mesh->faceGroupCount() + (mesh->ignoredFaceCount() > 0 ? 1 : 0));
Array<CreateChartGroupTaskArgs> taskArgs;
taskArgs.resize(chartGroups.size());
for (uint32_t g = 0; g < chartGroups.size(); g++) {
CreateChartGroupTaskArgs &args = taskArgs[g];
args.chartGroup = &chartGroups[g];
- args.faceGroup = faceGroups[g];
+ args.faceGroup = uint16_t(g < mesh->faceGroupCount() ? g : Mesh::kInvalidFaceGroup);
args.groupId = g;
args.mesh = mesh;
}
@@ -6561,6 +7544,8 @@ public:
chartGroupCount++;
}
Progress progress(ProgressCategory::ComputeCharts, progressFunc, progressUserData, chartGroupCount);
+ ThreadLocal<segment::Atlas> atlas;
+ ThreadLocal<ChartCtorBuffers> chartBuffers;
Array<ComputeChartsTaskArgs> taskArgs;
taskArgs.reserve(chartGroupCount);
for (uint32_t i = 0; i < m_chartGroups.size(); i++) {
@@ -6568,6 +7553,8 @@ public:
ComputeChartsTaskArgs args;
args.taskScheduler = taskScheduler;
args.chartGroup = m_chartGroups[i];
+ args.atlas = &atlas;
+ args.chartBuffers = &chartBuffers;
args.options = &options;
args.progress = &progress;
taskArgs.push_back(args);
@@ -6605,6 +7592,11 @@ public:
chartGroupCount++;
}
Progress progress(ProgressCategory::ParameterizeCharts, progressFunc, progressUserData, chartGroupCount);
+ ThreadLocal<UniformGrid2> boundaryGrid; // For Quality boundary intersection.
+ ThreadLocal<ChartCtorBuffers> chartBuffers;
+#if XA_RECOMPUTE_CHARTS
+ ThreadLocal<PiecewiseParam> piecewiseParam;
+#endif
Array<ParameterizeChartsTaskArgs> taskArgs;
taskArgs.reserve(chartGroupCount);
for (uint32_t i = 0; i < m_chartGroups.size(); i++) {
@@ -6613,6 +7605,11 @@ public:
args.taskScheduler = taskScheduler;
args.chartGroup = m_chartGroups[i];
args.func = func;
+ args.boundaryGrid = &boundaryGrid;
+ args.chartBuffers = &chartBuffers;
+#if XA_RECOMPUTE_CHARTS
+ args.piecewiseParam = &piecewiseParam;
+#endif
args.progress = &progress;
taskArgs.push_back(args);
}
@@ -6646,55 +7643,6 @@ private:
namespace pack {
-#if XA_DEBUG_EXPORT_ATLAS_IMAGES
-const uint8_t TGA_TYPE_RGB = 2;
-const uint8_t TGA_ORIGIN_UPPER = 0x20;
-
-#pragma pack(push, 1)
-struct TgaHeader
-{
- uint8_t id_length;
- uint8_t colormap_type;
- uint8_t image_type;
- uint16_t colormap_index;
- uint16_t colormap_length;
- uint8_t colormap_size;
- uint16_t x_origin;
- uint16_t y_origin;
- uint16_t width;
- uint16_t height;
- uint8_t pixel_size;
- uint8_t flags;
- enum { Size = 18 };
-};
-#pragma pack(pop)
-
-static void WriteTga(const char *filename, const uint8_t *data, uint32_t width, uint32_t height)
-{
- XA_DEBUG_ASSERT(sizeof(TgaHeader) == TgaHeader::Size);
- FILE *f;
- XA_FOPEN(f, filename, "wb");
- if (!f)
- return;
- TgaHeader tga;
- tga.id_length = 0;
- tga.colormap_type = 0;
- tga.image_type = TGA_TYPE_RGB;
- tga.colormap_index = 0;
- tga.colormap_length = 0;
- tga.colormap_size = 0;
- tga.x_origin = 0;
- tga.y_origin = 0;
- tga.width = (uint16_t)width;
- tga.height = (uint16_t)height;
- tga.pixel_size = 24;
- tga.flags = TGA_ORIGIN_UPPER;
- fwrite(&tga, sizeof(TgaHeader), 1, f);
- fwrite(data, sizeof(uint8_t), width * height * 3, f);
- fclose(f);
-}
-#endif
-
class AtlasImage
{
public:
@@ -6728,13 +7676,13 @@ public:
const int xx = x + offset_x;
if (xx >= 0 && xx < atlas_w && yy < atlas_h) {
const uint32_t dataOffset = xx + yy * m_width;
- if (image->bitAt(x, y)) {
+ if (image->get(x, y)) {
XA_DEBUG_ASSERT(m_data[dataOffset] == 0);
m_data[dataOffset] = chartIndex | kImageHasChartIndexBit;
- } else if (imageBilinear && imageBilinear->bitAt(x, y)) {
+ } else if (imageBilinear && imageBilinear->get(x, y)) {
XA_DEBUG_ASSERT(m_data[dataOffset] == 0);
m_data[dataOffset] = chartIndex | kImageHasChartIndexBit | kImageIsBilinearBit;
- } else if (imagePadding && imagePadding->bitAt(x, y)) {
+ } else if (imagePadding && imagePadding->get(x, y)) {
XA_DEBUG_ASSERT(m_data[dataOffset] == 0);
m_data[dataOffset] = chartIndex | kImageHasChartIndexBit | kImageIsPaddingBit;
}
@@ -6807,6 +7755,8 @@ struct Chart
bool allowRotate;
// bounding box
Vector2 majorAxis, minorAxis, minCorner, maxCorner;
+ // Mesh only
+ const Array<uint32_t> *boundaryEdges;
// UvMeshChart only
Array<uint32_t> faces;
@@ -6816,6 +7766,7 @@ struct Chart
struct AddChartTaskArgs
{
+ ThreadLocal<BoundingBox2D> *boundingBox;
param::Chart *paramChart;
Chart *chart; // out
};
@@ -6834,102 +7785,32 @@ static void runAddChartTask(void *userData)
chart->material = 0;
chart->indexCount = mesh->indexCount();
chart->indices = mesh->indices();
- chart->parametricArea = paramChart->computeParametricArea();
+ chart->parametricArea = mesh->computeParametricArea();
if (chart->parametricArea < kAreaEpsilon) {
// When the parametric area is too small we use a rough approximation to prevent divisions by very small numbers.
const Vector2 bounds = paramChart->computeParametricBounds();
chart->parametricArea = bounds.x * bounds.y;
}
- chart->surfaceArea = paramChart->computeSurfaceArea();
+ chart->surfaceArea = mesh->computeSurfaceArea();
chart->vertices = mesh->texcoords();
chart->vertexCount = mesh->vertexCount();
chart->allowRotate = true;
- // Compute list of boundary vertices.
- Array<Vector2> boundary;
- boundary.reserve(16);
+ chart->boundaryEdges = &mesh->boundaryEdges();
+ // Compute bounding box of chart.
+ BoundingBox2D &bb = args->boundingBox->get();
+ bb.clear();
for (uint32_t v = 0; v < chart->vertexCount; v++) {
if (mesh->isBoundaryVertex(v))
- boundary.push_back(mesh->texcoord(v));
+ bb.appendBoundaryVertex(mesh->texcoord(v));
}
- XA_DEBUG_ASSERT(boundary.size() > 0);
- // Compute bounding box of chart.
- static thread_local BoundingBox2D boundingBox;
- boundingBox.compute(boundary.data(), boundary.size(), mesh->texcoords(), mesh->vertexCount());
- chart->majorAxis = boundingBox.majorAxis();
- chart->minorAxis = boundingBox.minorAxis();
- chart->minCorner = boundingBox.minCorner();
- chart->maxCorner = boundingBox.maxCorner();
+ bb.compute(mesh->texcoords(), mesh->vertexCount());
+ chart->majorAxis = bb.majorAxis;
+ chart->minorAxis = bb.minorAxis;
+ chart->minCorner = bb.minCorner;
+ chart->maxCorner = bb.maxCorner;
XA_PROFILE_END(packChartsAddChartsThread)
}
-struct FindChartLocationBruteForceTaskArgs
-{
- std::atomic<bool> *finished; // One of the tasks found a location that doesn't expand the atlas.
- Vector2i startPosition;
- const BitImage *atlasBitImage;
- const BitImage *chartBitImage;
- const BitImage *chartBitImageRotated;
- int w, h;
- bool blockAligned, allowRotate;
- uint32_t maxResolution;
- // out
- bool best_insideAtlas;
- int best_metric, best_x, best_y, best_w, best_h, best_r;
-};
-
-static void runFindChartLocationBruteForceTask(void *userData)
-{
- XA_PROFILE_START(packChartsFindLocationThread)
- auto args = (FindChartLocationBruteForceTaskArgs *)userData;
- args->best_metric = INT_MAX;
- if (args->finished->load())
- return;
- // Try two different orientations.
- for (int r = 0; r < 2; r++) {
- if (args->finished->load())
- break;
- int cw = args->chartBitImage->width();
- int ch = args->chartBitImage->height();
- if (r == 1) {
- if (args->allowRotate)
- swap(cw, ch);
- else
- break;
- }
- const int y = args->startPosition.y;
- const int stepSize = args->blockAligned ? 4 : 1;
- for (int x = args->startPosition.x; x <= args->w + stepSize; x += stepSize) {
- if (args->maxResolution > 0 && (x > (int)args->maxResolution - cw || y > (int)args->maxResolution - ch))
- continue;
- if (args->finished->load())
- break;
- // Early out if metric not better.
- const int area = max(args->w, x + cw) * max(args->h, y + ch);
- const int extents = max(max(args->w, x + cw), max(args->h, y + ch));
- const int metric = extents * extents + area;
- if (metric > args->best_metric)
- continue;
- // If metric is the same, pick the one closest to the origin.
- if (metric == args->best_metric && max(x, y) >= max(args->best_x, args->best_y))
- continue;
- if (!args->atlasBitImage->canBlit(r == 1 ? *(args->chartBitImageRotated) : *(args->chartBitImage), x, y))
- continue;
- args->best_metric = metric;
- args->best_insideAtlas = area == args->w * args->h;
- args->best_x = x;
- args->best_y = y;
- args->best_w = cw;
- args->best_h = ch;
- args->best_r = r;
- if (args->best_insideAtlas) {
- args->finished->store(true);
- break;
- }
- }
- }
- XA_PROFILE_END(packChartsFindLocationThread)
-}
-
struct Atlas
{
~Atlas()
@@ -6975,6 +7856,7 @@ struct Atlas
taskArgs.resize(chartCount);
TaskGroupHandle taskGroup = taskScheduler->createTaskGroup(chartCount);
uint32_t chartIndex = 0;
+ ThreadLocal<BoundingBox2D> boundingBox;
for (uint32_t i = 0; i < chartGroupsCount; i++) {
const param::ChartGroup *chartGroup = paramAtlas->chartGroupAt(i);
if (chartGroup->isVertexMap())
@@ -6982,6 +7864,7 @@ struct Atlas
const uint32_t count = chartGroup->chartCount();
for (uint32_t j = 0; j < count; j++) {
AddChartTaskArgs &args = taskArgs[chartIndex];
+ args.boundingBox = &boundingBox;
args.paramChart = chartGroup->chartAt(j);
Task task;
task.userData = &taskArgs[chartIndex];
@@ -7000,8 +7883,6 @@ struct Atlas
void addUvMeshCharts(UvMeshInstance *mesh)
{
BitArray vertexUsed(mesh->texcoords.size());
- Array<Vector2> boundary;
- boundary.reserve(16);
BoundingBox2D boundingBox;
for (uint32_t c = 0; c < mesh->mesh->charts.size(); c++) {
UvMeshChart *uvChart = mesh->mesh->charts[c];
@@ -7013,14 +7894,15 @@ struct Atlas
chart->vertices = mesh->texcoords.data();
chart->vertexCount = mesh->texcoords.size();
chart->allowRotate = mesh->rotateCharts;
+ chart->boundaryEdges = nullptr;
chart->faces.resize(uvChart->faces.size());
memcpy(chart->faces.data(), uvChart->faces.data(), sizeof(uint32_t) * uvChart->faces.size());
// Find unique vertices.
- vertexUsed.clearAll();
+ vertexUsed.zeroOutMemory();
for (uint32_t i = 0; i < chart->indexCount; i++) {
const uint32_t vertex = chart->indices[i];
- if (!vertexUsed.bitAt(vertex)) {
- vertexUsed.setBitAt(vertex);
+ if (!vertexUsed.get(vertex)) {
+ vertexUsed.set(vertex);
chart->uniqueVertices.push_back(vertex);
}
}
@@ -7045,24 +7927,22 @@ struct Atlas
const Vector2 bounds = (maxCorner - minCorner) * 0.5f;
chart->parametricArea = bounds.x * bounds.y;
}
- // Compute list of boundary vertices.
+ // Compute bounding box of chart.
// Using all unique vertices for simplicity, can compute real boundaries if this is too slow.
- boundary.clear();
+ boundingBox.clear();
for (uint32_t v = 0; v < chart->uniqueVertexCount(); v++)
- boundary.push_back(chart->uniqueVertexAt(v));
- XA_DEBUG_ASSERT(boundary.size() > 0);
- // Compute bounding box of chart.
- boundingBox.compute(boundary.data(), boundary.size(), boundary.data(), boundary.size());
- chart->majorAxis = boundingBox.majorAxis();
- chart->minorAxis = boundingBox.minorAxis();
- chart->minCorner = boundingBox.minCorner();
- chart->maxCorner = boundingBox.maxCorner();
+ boundingBox.appendBoundaryVertex(chart->uniqueVertexAt(v));
+ boundingBox.compute();
+ chart->majorAxis = boundingBox.majorAxis;
+ chart->minorAxis = boundingBox.minorAxis;
+ chart->minCorner = boundingBox.minCorner;
+ chart->maxCorner = boundingBox.maxCorner;
m_charts.push_back(chart);
}
}
// Pack charts in the smallest possible rectangle.
- bool packCharts(TaskScheduler *taskScheduler, const PackOptions &options, ProgressFunc progressFunc, void *progressUserData)
+ bool packCharts(const PackOptions &options, ProgressFunc progressFunc, void *progressUserData)
{
if (progressFunc) {
if (!progressFunc(ProgressCategory::PackCharts, 0, progressUserData))
@@ -7107,10 +7987,11 @@ struct Atlas
for (uint32_t c = 0; c < chartCount; c++) {
Chart *chart = m_charts[c];
// Compute chart scale
- float scale = (chart->surfaceArea / chart->parametricArea) * m_texelsPerUnit;
- if (chart->parametricArea == 0.0f)
- scale = 0;
- XA_ASSERT(isFinite(scale));
+ float scale = 1.0f;
+ if (chart->parametricArea != 0.0f) {
+ scale = (chart->surfaceArea / chart->parametricArea) * m_texelsPerUnit;
+ XA_ASSERT(isFinite(scale));
+ }
// Translate, rotate and scale vertices. Compute extents.
Vector2 minCorner(FLT_MAX, FLT_MAX);
if (!chart->allowRotate) {
@@ -7181,6 +8062,8 @@ struct Atlas
texcoord.y += 0.5f + options.padding;
extents = max(extents, texcoord);
}
+ if (extents.x > resolution || extents.y > resolution)
+ XA_PRINT(" Chart %u extents are large (%gx%g)\n", c, extents.x, extents.y);
chartExtents[c] = extents;
chartOrderArray[c] = extents.x + extents.y; // Use perimeter for chart sort key.
minChartPerimeter = min(minChartPerimeter, chartOrderArray[c]);
@@ -7207,6 +8090,7 @@ struct Atlas
// Rotated versions swap x and y.
BitImage chartImage, chartImageBilinear, chartImagePadding;
BitImage chartImageRotated, chartImageBilinearRotated, chartImagePaddingRotated;
+ UniformGrid2 boundaryEdgeGrid;
Array<Vector2i> atlasSizes;
atlasSizes.push_back(Vector2i(0, 0));
int progress = 0;
@@ -7249,7 +8133,7 @@ struct Atlas
}
// Expand chart by pixels sampled by bilinear interpolation.
if (options.bilinear)
- bilinearExpand(chart, &chartImage, &chartImageBilinear, chart->allowRotate ? &chartImageBilinearRotated : nullptr);
+ bilinearExpand(chart, &chartImage, &chartImageBilinear, chart->allowRotate ? &chartImageBilinearRotated : nullptr, boundaryEdgeGrid);
// Expand chart by padding pixels (dilation).
if (options.padding > 0) {
// Copy into the same BitImage instances for every chart to avoid reallocating BitImage buffers (largest chart is packed first).
@@ -7310,7 +8194,7 @@ struct Atlas
chartStartPositions.push_back(Vector2i(0, 0));
}
XA_PROFILE_START(packChartsFindLocation)
- const bool foundLocation = findChartLocation(taskScheduler, chartStartPositions[currentAtlas], options.bruteForce, m_bitImages[currentAtlas], chartImageToPack, chartImageToPackRotated, atlasSizes[currentAtlas].x, atlasSizes[currentAtlas].y, &best_x, &best_y, &best_cw, &best_ch, &best_r, options.blockAlign, maxResolution, chart->allowRotate);
+ const bool foundLocation = findChartLocation(chartStartPositions[currentAtlas], options.bruteForce, m_bitImages[currentAtlas], chartImageToPack, chartImageToPackRotated, atlasSizes[currentAtlas].x, atlasSizes[currentAtlas].y, &best_x, &best_y, &best_cw, &best_ch, &best_r, options.blockAlign, maxResolution, chart->allowRotate);
XA_PROFILE_END(packChartsFindLocation)
XA_DEBUG_ASSERT(!(firstChartInBitImage && !foundLocation)); // Chart doesn't fit in an empty, newly allocated bitImage. Shouldn't happen, since charts are resized if they are too big to fit in the atlas.
if (maxResolution == 0) {
@@ -7359,6 +8243,13 @@ struct Atlas
} else {
m_atlasImages[currentAtlas]->addChart(c, &chartImageRotated, options.bilinear ? &chartImageBilinearRotated : nullptr, options.padding > 0 ? &chartImagePaddingRotated : nullptr, atlasSizes[currentAtlas].x, atlasSizes[currentAtlas].y, best_x, best_y);
}
+#if XA_DEBUG_EXPORT_ATLAS_IMAGES && XA_DEBUG_EXPORT_ATLAS_IMAGES_PER_CHART
+ for (uint32_t j = 0; j < m_atlasImages.size(); j++) {
+ char filename[256];
+ XA_SPRINTF(filename, sizeof(filename), "debug_atlas_image%02u_chart%04u.tga", j, i);
+ m_atlasImages[j]->writeTga(filename, (uint32_t)atlasSizes[j].x, (uint32_t)atlasSizes[j].y);
+ }
+#endif
}
chart->atlasIndex = (int32_t)currentAtlas;
// Modify texture coordinates:
@@ -7415,7 +8306,7 @@ struct Atlas
uint32_t count = 0;
for (uint32_t y = 0; y < m_height; y++) {
for (uint32_t x = 0; x < m_width; x++)
- count += m_bitImages[i]->bitAt(x, y);
+ count += m_bitImages[i]->get(x, y);
}
m_utilization[i] = float(count) / (m_width * m_height);
}
@@ -7445,70 +8336,56 @@ private:
// is occupied at this point. At the end we have many small charts and a large atlas with sparse holes. Finding those holes randomly is slow. A better approach would be to
// start stacking large charts as if they were tetris pieces. Once charts get small try to place them randomly. It may be interesting to try a intermediate strategy, first try
// along one axis and then try exhaustively along that axis.
- bool findChartLocation(TaskScheduler *taskScheduler, const Vector2i &startPosition, bool bruteForce, const BitImage *atlasBitImage, const BitImage *chartBitImage, const BitImage *chartBitImageRotated, int w, int h, int *best_x, int *best_y, int *best_w, int *best_h, int *best_r, bool blockAligned, uint32_t maxResolution, bool allowRotate)
+ bool findChartLocation(const Vector2i &startPosition, bool bruteForce, const BitImage *atlasBitImage, const BitImage *chartBitImage, const BitImage *chartBitImageRotated, int w, int h, int *best_x, int *best_y, int *best_w, int *best_h, int *best_r, bool blockAligned, uint32_t maxResolution, bool allowRotate)
{
const int attempts = 4096;
if (bruteForce || attempts >= w * h)
- return findChartLocation_bruteForce(taskScheduler, startPosition, atlasBitImage, chartBitImage, chartBitImageRotated, w, h, best_x, best_y, best_w, best_h, best_r, blockAligned, maxResolution, allowRotate);
+ return findChartLocation_bruteForce(startPosition, atlasBitImage, chartBitImage, chartBitImageRotated, w, h, best_x, best_y, best_w, best_h, best_r, blockAligned, maxResolution, allowRotate);
return findChartLocation_random(atlasBitImage, chartBitImage, chartBitImageRotated, w, h, best_x, best_y, best_w, best_h, best_r, attempts, blockAligned, maxResolution, allowRotate);
}
- bool findChartLocation_bruteForce(TaskScheduler *taskScheduler, const Vector2i &startPosition, const BitImage *atlasBitImage, const BitImage *chartBitImage, const BitImage *chartBitImageRotated, int w, int h, int *best_x, int *best_y, int *best_w, int *best_h, int *best_r, bool blockAligned, uint32_t maxResolution, bool allowRotate)
+ bool findChartLocation_bruteForce(const Vector2i &startPosition, const BitImage *atlasBitImage, const BitImage *chartBitImage, const BitImage *chartBitImageRotated, int w, int h, int *best_x, int *best_y, int *best_w, int *best_h, int *best_r, bool blockAligned, uint32_t maxResolution, bool allowRotate)
{
const int stepSize = blockAligned ? 4 : 1;
- const int chartMinHeight = min(chartBitImage->height(), chartBitImageRotated->height());
- uint32_t taskCount = 0;
- for (int y = startPosition.y; y <= h + stepSize; y += stepSize) {
- if (maxResolution > 0 && y > (int)maxResolution - chartMinHeight)
- break;
- taskCount++;
- }
- m_bruteForceTaskArgs.clear();
- m_bruteForceTaskArgs.resize(taskCount);
- TaskGroupHandle taskGroup = taskScheduler->createTaskGroup(taskCount);
- std::atomic<bool> finished(false); // One of the tasks found a location that doesn't expand the atlas.
- uint32_t i = 0;
- for (int y = startPosition.y; y <= h + stepSize; y += stepSize) {
- if (maxResolution > 0 && y > (int)maxResolution - chartMinHeight)
- break;
- FindChartLocationBruteForceTaskArgs &args = m_bruteForceTaskArgs[i];
- args.finished = &finished;
- args.startPosition = Vector2i(y == startPosition.y ? startPosition.x : 0, y);
- args.atlasBitImage = atlasBitImage;
- args.chartBitImage = chartBitImage;
- args.chartBitImageRotated = chartBitImageRotated;
- args.w = w;
- args.h = h;
- args.blockAligned = blockAligned;
- args.allowRotate = allowRotate;
- args.maxResolution = maxResolution;
- Task task;
- task.userData = &m_bruteForceTaskArgs[i];
- task.func = runFindChartLocationBruteForceTask;
- taskScheduler->run(taskGroup, task);
- i++;
- }
- taskScheduler->wait(&taskGroup);
- // Find the task result with the best metric.
int best_metric = INT_MAX;
- bool best_insideAtlas = false;
- for (i = 0; i < taskCount; i++) {
- FindChartLocationBruteForceTaskArgs &args = m_bruteForceTaskArgs[i];
- if (args.best_metric > best_metric)
- continue;
- // A location that doesn't expand the atlas is always preferred.
- if (!args.best_insideAtlas && best_insideAtlas)
- continue;
- // If metric is the same, pick the one closest to the origin.
- if (args.best_insideAtlas == best_insideAtlas && args.best_metric == best_metric && max(args.best_x, args.best_y) >= max(*best_x, *best_y))
- continue;
- best_metric = args.best_metric;
- best_insideAtlas = args.best_insideAtlas;
- *best_x = args.best_x;
- *best_y = args.best_y;
- *best_w = args.best_w;
- *best_h = args.best_h;
- *best_r = args.best_r;
+ // Try two different orientations.
+ for (int r = 0; r < 2; r++) {
+ int cw = chartBitImage->width();
+ int ch = chartBitImage->height();
+ if (r == 1) {
+ if (allowRotate)
+ swap(cw, ch);
+ else
+ break;
+ }
+ for (int y = startPosition.y; y <= h + stepSize; y += stepSize) {
+ if (maxResolution > 0 && y > (int)maxResolution - ch)
+ break;
+ for (int x = (y == startPosition.y ? startPosition.x : 0); x <= w + stepSize; x += stepSize) {
+ if (maxResolution > 0 && x > (int)maxResolution - cw)
+ break;
+ // Early out if metric is not better.
+ const int extentX = max(w, x + cw), extentY = max(h, y + ch);
+ const int area = extentX * extentY;
+ const int extents = max(extentX, extentY);
+ const int metric = extents * extents + area;
+ if (metric > best_metric)
+ continue;
+ // If metric is the same, pick the one closest to the origin.
+ if (metric == best_metric && max(x, y) >= max(*best_x, *best_y))
+ continue;
+ if (!atlasBitImage->canBlit(r == 1 ? *chartBitImageRotated : *chartBitImage, x, y))
+ continue;
+ best_metric = metric;
+ *best_x = x;
+ *best_y = y;
+ *best_w = cw;
+ *best_h = ch;
+ *best_r = r;
+ if (area == w * h)
+ return true; // Chart is completely inside, do not look at any other location.
+ }
+ }
}
return best_metric != INT_MAX;
}
@@ -7581,10 +8458,10 @@ private:
for (int x = 0; x < w; x++) {
int xx = x + offset_x;
if (xx >= 0) {
- if (image->bitAt(x, y)) {
+ if (image->get(x, y)) {
if (xx < atlas_w && yy < atlas_h) {
- XA_DEBUG_ASSERT(atlasBitImage->bitAt(xx, yy) == false);
- atlasBitImage->setBitAt(xx, yy);
+ XA_DEBUG_ASSERT(atlasBitImage->get(xx, yy) == false);
+ atlasBitImage->set(xx, yy);
}
}
}
@@ -7593,14 +8470,23 @@ private:
}
}
- void bilinearExpand(const Chart *chart, BitImage *source, BitImage *dest, BitImage *destRotated) const
+ void bilinearExpand(const Chart *chart, BitImage *source, BitImage *dest, BitImage *destRotated, UniformGrid2 &boundaryEdgeGrid) const
{
+ boundaryEdgeGrid.reset(chart->vertices, chart->indices);
+ if (chart->boundaryEdges) {
+ const uint32_t edgeCount = chart->boundaryEdges->size();
+ for (uint32_t i = 0; i < edgeCount; i++)
+ boundaryEdgeGrid.append((*chart->boundaryEdges)[i]);
+ } else {
+ for (uint32_t i = 0; i < chart->indexCount; i++)
+ boundaryEdgeGrid.append(i);
+ }
const int xOffsets[] = { -1, 0, 1, -1, 1, -1, 0, 1 };
const int yOffsets[] = { -1, -1, -1, 0, 0, 1, 1, 1 };
for (uint32_t y = 0; y < source->height(); y++) {
for (uint32_t x = 0; x < source->width(); x++) {
// Copy pixels from source.
- if (source->bitAt(x, y))
+ if (source->get(x, y))
goto setPixel;
// Empty pixel. If none of of the surrounding pixels are set, this pixel can't be sampled by bilinear interpolation.
{
@@ -7610,44 +8496,32 @@ private:
const int sy = (int)y + yOffsets[s];
if (sx < 0 || sy < 0 || sx >= (int)source->width() || sy >= (int)source->height())
continue;
- if (source->bitAt((uint32_t)sx, (uint32_t)sy))
+ if (source->get((uint32_t)sx, (uint32_t)sy))
break;
}
if (s == 8)
continue;
}
- // If a 2x2 square centered on the pixels centroid intersects the triangle, this pixel will be sampled by bilinear interpolation.
- // See "Precomputed Global Illumination in Frostbite (GDC 2018)" page 95
- for (uint32_t f = 0; f < chart->indexCount / 3; f++) {
+ {
+ // If a 2x2 square centered on the pixels centroid intersects the triangle, this pixel will be sampled by bilinear interpolation.
+ // See "Precomputed Global Illumination in Frostbite (GDC 2018)" page 95
const Vector2 centroid((float)x + 0.5f, (float)y + 0.5f);
- Vector2 vertices[3];
- for (uint32_t i = 0; i < 3; i++)
- vertices[i] = chart->vertices[chart->indices[f * 3 + i]];
- // Test for triangle vertex in square bounds.
- for (uint32_t i = 0; i < 3; i++) {
- const Vector2 &v = vertices[i];
- if (v.x > centroid.x - 1.0f && v.x < centroid.x + 1.0f && v.y > centroid.y - 1.0f && v.y < centroid.y + 1.0f)
- goto setPixel;
- }
- // Test for triangle edge intersection with square edge.
const Vector2 squareVertices[4] = {
Vector2(centroid.x - 1.0f, centroid.y - 1.0f),
Vector2(centroid.x + 1.0f, centroid.y - 1.0f),
Vector2(centroid.x + 1.0f, centroid.y + 1.0f),
Vector2(centroid.x - 1.0f, centroid.y + 1.0f)
};
- for (uint32_t i = 0; i < 3; i++) {
- for (uint32_t j = 0; j < 4; j++) {
- if (linesIntersect(vertices[i], vertices[(i + 1) % 3], squareVertices[j], squareVertices[(j + 1) % 4], 0.0f))
- goto setPixel;
- }
+ for (uint32_t j = 0; j < 4; j++) {
+ if (boundaryEdgeGrid.intersect(squareVertices[j], squareVertices[(j + 1) % 4], 0.0f))
+ goto setPixel;
}
}
continue;
setPixel:
- dest->setBitAt(x, y);
+ dest->set(x, y);
if (destRotated)
- destRotated->setBitAt(y, x);
+ destRotated->set(y, x);
}
}
}
@@ -7660,9 +8534,9 @@ private:
static bool drawTriangleCallback(void *param, int x, int y)
{
auto args = (DrawTriangleCallbackArgs *)param;
- args->chartBitImage->setBitAt(x, y);
+ args->chartBitImage->set(x, y);
if (args->chartBitImageRotated)
- args->chartBitImageRotated->setBitAt(y, x);
+ args->chartBitImageRotated->set(y, x);
return true;
}
@@ -7670,7 +8544,6 @@ private:
Array<float> m_utilization;
Array<BitImage *> m_bitImages;
Array<Chart *> m_charts;
- Array<FindChartLocationBruteForceTaskArgs> m_bruteForceTaskArgs;
RadixSort m_radix;
uint32_t m_width = 0;
uint32_t m_height = 0;
@@ -7789,13 +8662,6 @@ static void runAddMeshTask(void *userData)
}
if (progress->cancel)
goto cleanup;
- {
- XA_PROFILE_START(addMeshCreateBoundaries)
- mesh->createBoundaries();
- XA_PROFILE_END(addMeshCreateBoundaries)
- }
- if (progress->cancel)
- goto cleanup;
#if XA_DEBUG_EXPORT_OBJ_SOURCE_MESHES
char filename[256];
XA_SPRINTF(filename, sizeof(filename), "debug_mesh_%03u.obj", mesh->id());
@@ -7805,22 +8671,22 @@ static void runAddMeshTask(void *userData)
mesh->writeObjVertices(file);
// groups
uint32_t numGroups = 0;
- for (uint32_t i = 0; i < mesh->faceGroupCount(); i++) {
- if (mesh->faceGroupAt(i) != UINT32_MAX)
+ for (uint32_t i = 0; i < mesh->faceCount(); i++) {
+ if (mesh->faceGroupAt(i) != Mesh::kInvalidFaceGroup)
numGroups = internal::max(numGroups, mesh->faceGroupAt(i) + 1);
}
for (uint32_t i = 0; i < numGroups; i++) {
fprintf(file, "o group_%04d\n", i);
fprintf(file, "s off\n");
- for (uint32_t f = 0; f < mesh->faceGroupCount(); f++) {
+ for (uint32_t f = 0; f < mesh->faceCount(); f++) {
if (mesh->faceGroupAt(f) == i)
mesh->writeObjFace(file, f);
}
}
fprintf(file, "o group_ignored\n");
fprintf(file, "s off\n");
- for (uint32_t f = 0; f < mesh->faceGroupCount(); f++) {
- if (mesh->faceGroupAt(f) == UINT32_MAX)
+ for (uint32_t f = 0; f < mesh->faceCount(); f++) {
+ if (mesh->faceGroupAt(f) == Mesh::kInvalidFaceGroup)
mesh->writeObjFace(file, f);
}
mesh->writeObjBoundaryEges(file);
@@ -8033,7 +8899,6 @@ void AddMeshJoin(Atlas *atlas)
XA_PROFILE_PRINT_AND_RESET(" Total (thread): ", addMeshThread)
XA_PROFILE_PRINT_AND_RESET(" Create colocals: ", addMeshCreateColocals)
XA_PROFILE_PRINT_AND_RESET(" Create face groups: ", addMeshCreateFaceGroups)
- XA_PROFILE_PRINT_AND_RESET(" Create boundaries: ", addMeshCreateBoundaries)
XA_PROFILE_PRINT_AND_RESET(" Create chart groups (real): ", addMeshCreateChartGroupsReal)
XA_PROFILE_PRINT_AND_RESET(" Create chart groups (thread): ", addMeshCreateChartGroupsThread)
XA_PRINT_MEM_USAGE
@@ -8044,16 +8909,7 @@ struct EdgeKey
EdgeKey() {}
EdgeKey(const EdgeKey &k) : v0(k.v0), v1(k.v1) {}
EdgeKey(uint32_t v0, uint32_t v1) : v0(v0), v1(v1) {}
-
- void operator=(const EdgeKey &k)
- {
- v0 = k.v0;
- v1 = k.v1;
- }
- bool operator==(const EdgeKey &k) const
- {
- return v0 == k.v0 && v1 == k.v1;
- }
+ bool operator==(const EdgeKey &k) const { return v0 == k.v0 && v1 == k.v1; }
uint32_t v0;
uint32_t v1;
@@ -8119,15 +8975,15 @@ AddMeshError::Enum AddUvMesh(Atlas *atlas, const UvMeshDecl &decl)
for (uint32_t i = 0; i < indexCount; i++)
vertexToFaceMap.add(meshInstance->texcoords[mesh->indices[i]]);
internal::BitArray faceAssigned(faceCount);
- faceAssigned.clearAll();
+ faceAssigned.zeroOutMemory();
for (uint32_t f = 0; f < faceCount; f++) {
- if (faceAssigned.bitAt(f))
+ if (faceAssigned.get(f))
continue;
// Found an unassigned face, create a new chart.
internal::UvMeshChart *chart = XA_NEW(internal::MemTag::Default, internal::UvMeshChart);
chart->material = decl.faceMaterialData ? decl.faceMaterialData[f] : 0;
// Walk incident faces and assign them to the chart.
- faceAssigned.setBitAt(f);
+ faceAssigned.set(f);
chart->faces.push_back(f);
for (;;) {
bool newFaceAssigned = false;
@@ -8140,8 +8996,8 @@ AddMeshError::Enum AddUvMesh(Atlas *atlas, const UvMeshDecl &decl)
while (mapIndex != UINT32_MAX) {
const uint32_t face2 = mapIndex / 3; // 3 vertices added per face.
// Materials must match.
- if (!faceAssigned.bitAt(face2) && (!decl.faceMaterialData || decl.faceMaterialData[face] == decl.faceMaterialData[face2])) {
- faceAssigned.setBitAt(face2);
+ if (!faceAssigned.get(face2) && (!decl.faceMaterialData || decl.faceMaterialData[face] == decl.faceMaterialData[face2])) {
+ faceAssigned.set(face2);
chart->faces.push_back(face2);
newFaceAssigned = true;
}
@@ -8202,6 +9058,7 @@ void ComputeCharts(Atlas *atlas, ChartOptions chartOptions)
continue;
for (uint32_t k = 0; k < chartGroup->chartCount(); k++) {
const internal::param::Chart *chart = chartGroup->chartAt(k);
+#if XA_PRINT_CHART_WARNINGS
if (chart->warningFlags() & internal::param::ChartWarningFlags::CloseHolesFailed)
XA_PRINT_WARNING(" Chart %u (mesh %u, group %u, id %u): failed to close holes\n", chartCount, i, j, k);
if (chart->warningFlags() & internal::param::ChartWarningFlags::FixTJunctionsDuplicatedEdge)
@@ -8210,8 +9067,7 @@ void ComputeCharts(Atlas *atlas, ChartOptions chartOptions)
XA_PRINT_WARNING(" Chart %u (mesh %u, group %u, id %u): fixing t-junctions failed\n", chartCount, i, j, k);
if (chart->warningFlags() & internal::param::ChartWarningFlags::TriangulateDuplicatedEdge)
XA_PRINT_WARNING(" Chart %u (mesh %u, group %u, id %u): triangulation created non-manifold geometry\n", chartCount, i, j, k);
- if (!chart->isDisk())
- XA_PRINT_WARNING(" Chart %u (mesh %u, group %u, id %u): doesn't have disk topology\n", chartCount, i, j, k);
+#endif
holesCount += chart->closedHolesCount();
if (chart->closedHolesCount() > 0)
chartsWithHolesCount++;
@@ -8279,7 +9135,7 @@ void ParameterizeCharts(Atlas *atlas, ParameterizeFunc func)
return;
}
XA_PROFILE_END(parameterizeChartsReal)
- uint32_t chartCount = 0, orthoChartsCount = 0, planarChartsCount = 0, chartsAddedCount = 0, chartsDeletedCount = 0;
+ uint32_t chartCount = 0, orthoChartsCount = 0, planarChartsCount = 0, lscmChartsCount = 0, piecewiseChartsCount = 0, chartsAddedCount = 0, chartsDeletedCount = 0;
for (uint32_t i = 0; i < ctx->meshCount; i++) {
for (uint32_t j = 0; j < ctx->paramAtlas.chartGroupCount(i); j++) {
const internal::param::ChartGroup *chartGroup = ctx->paramAtlas.chartGroupAt(i, j);
@@ -8287,19 +9143,23 @@ void ParameterizeCharts(Atlas *atlas, ParameterizeFunc func)
continue;
for (uint32_t k = 0; k < chartGroup->chartCount(); k++) {
const internal::param::Chart *chart = chartGroup->chartAt(k);
- if (chart->isPlanar())
+ if (chart->type() == ChartType::Planar)
planarChartsCount++;
- else if (chart->isOrtho())
+ else if (chart->type() == ChartType::Ortho)
orthoChartsCount++;
+ else if (chart->type() == ChartType::LSCM)
+ lscmChartsCount++;
+ else if (chart->type() == ChartType::Piecewise)
+ piecewiseChartsCount++;
}
chartCount += chartGroup->chartCount();
chartsAddedCount += chartGroup->paramAddedChartsCount();
chartsDeletedCount += chartGroup->paramDeletedChartsCount();
}
}
- XA_PRINT(" %u planar charts, %u ortho charts, %u other\n", planarChartsCount, orthoChartsCount, chartCount - (planarChartsCount + orthoChartsCount));
+ XA_PRINT(" %u planar charts, %u ortho charts, %u LSCM charts, %u piecewise charts\n", planarChartsCount, orthoChartsCount, lscmChartsCount, piecewiseChartsCount);
if (chartsDeletedCount > 0) {
- XA_PRINT(" %u charts deleted due to invalid parameterizations, %u new charts added\n", chartsDeletedCount, chartsAddedCount);
+ XA_PRINT(" %u charts with invalid parameterizations replaced with %u new charts\n", chartsDeletedCount, chartsAddedCount);
XA_PRINT(" %u charts\n", chartCount);
}
uint32_t chartIndex = 0, invalidParamCount = 0;
@@ -8310,7 +9170,7 @@ void ParameterizeCharts(Atlas *atlas, ParameterizeFunc func)
continue;
for (uint32_t k = 0; k < chartGroup->chartCount(); k++) {
const internal::param::Chart *chart = chartGroup->chartAt(k);
- const internal::param::ParameterizationQuality &quality = chart->paramQuality();
+ const internal::param::Quality &quality = chart->quality();
#if XA_DEBUG_EXPORT_OBJ_CHARTS_AFTER_PARAMETERIZATION
{
char filename[256];
@@ -8319,13 +9179,20 @@ void ParameterizeCharts(Atlas *atlas, ParameterizeFunc func)
}
#endif
bool invalid = false;
+ const char *type = "LSCM";
+ if (chart->type() == ChartType::Planar)
+ type = "planar";
+ else if (chart->type() == ChartType::Ortho)
+ type = "ortho";
+ else if (chart->type() == ChartType::Piecewise)
+ type = "piecewise";
if (quality.boundaryIntersection) {
invalid = true;
- XA_PRINT_WARNING(" Chart %u (mesh %u, group %u, id %u) (%s): invalid parameterization, self-intersecting boundary.\n", chartIndex, i, j, k, chart->isPlanar() ? "planar" : chart->isOrtho() ? "ortho" : "other");
+ XA_PRINT_WARNING(" Chart %u (mesh %u, group %u, id %u) (%s): invalid parameterization, self-intersecting boundary.\n", chartIndex, i, j, k, type);
}
if (quality.flippedTriangleCount > 0) {
invalid = true;
- XA_PRINT_WARNING(" Chart %u (mesh %u, group %u, id %u) (%s): invalid parameterization, %u / %u flipped triangles.\n", chartIndex, i, j, k, chart->isPlanar() ? "planar" : chart->isOrtho() ? "ortho" : "other", quality.flippedTriangleCount, quality.totalTriangleCount);
+ XA_PRINT_WARNING(" Chart %u (mesh %u, group %u, id %u) (%s): invalid parameterization, %u / %u flipped triangles.\n", chartIndex, i, j, k, type, quality.flippedTriangleCount, quality.totalTriangleCount);
}
if (invalid)
invalidParamCount++;
@@ -8415,7 +9282,7 @@ void PackCharts(Atlas *atlas, PackOptions packOptions)
packAtlas.addCharts(ctx->taskScheduler, &ctx->paramAtlas);
XA_PROFILE_END(packChartsAddCharts)
XA_PROFILE_START(packCharts)
- if (!packAtlas.packCharts(ctx->taskScheduler, packOptions, ctx->progressFunc, ctx->progressUserData))
+ if (!packAtlas.packCharts(packOptions, ctx->progressFunc, ctx->progressUserData))
return;
XA_PROFILE_END(packCharts)
// Populate atlas object with pack results.
@@ -8440,8 +9307,7 @@ void PackCharts(Atlas *atlas, PackOptions packOptions)
XA_PROFILE_PRINT_AND_RESET(" Restore texcoords: ", packChartsAddChartsRestoreTexcoords)
XA_PROFILE_PRINT_AND_RESET(" Rasterize: ", packChartsRasterize)
XA_PROFILE_PRINT_AND_RESET(" Dilate (padding): ", packChartsDilate)
- XA_PROFILE_PRINT_AND_RESET(" Find location (real): ", packChartsFindLocation)
- XA_PROFILE_PRINT_AND_RESET(" Find location (thread): ", packChartsFindLocationThread)
+ XA_PROFILE_PRINT_AND_RESET(" Find location: ", packChartsFindLocation)
XA_PROFILE_PRINT_AND_RESET(" Blit: ", packChartsBlit)
XA_PRINT_MEM_USAGE
XA_PRINT("Building output meshes\n");
@@ -8527,9 +9393,7 @@ void PackCharts(Atlas *atlas, PackOptions packOptions)
const int32_t atlasIndex = packAtlas.getChart(chartIndex)->atlasIndex;
XA_DEBUG_ASSERT(atlasIndex >= 0);
outputChart->atlasIndex = (uint32_t)atlasIndex;
- outputChart->flags = 0;
- if (chart->paramQuality().boundaryIntersection || chart->paramQuality().flippedTriangleCount > 0)
- outputChart->flags |= ChartFlags::Invalid;
+ outputChart->type = chart->type();
outputChart->faceCount = mesh->faceCount();
outputChart->faceArray = XA_ALLOC_ARRAY(internal::MemTag::Default, uint32_t, outputChart->faceCount);
for (uint32_t f = 0; f < outputChart->faceCount; f++)
diff --git a/thirdparty/xatlas/xatlas.h b/thirdparty/xatlas/xatlas.h
index 7be165e7e5..e59f493287 100644
--- a/thirdparty/xatlas/xatlas.h
+++ b/thirdparty/xatlas/xatlas.h
@@ -35,11 +35,14 @@ Copyright NVIDIA Corporation 2006 -- Ignacio Castano <icastano@nvidia.com>
namespace xatlas {
-struct ChartFlags
+struct ChartType
{
- enum
+ enum Enum
{
- Invalid = 1 << 0
+ Planar,
+ Ortho,
+ LSCM,
+ Piecewise
};
};
@@ -47,10 +50,10 @@ struct ChartFlags
struct Chart
{
uint32_t atlasIndex; // Sub-atlas index.
- uint32_t flags;
uint32_t *faceArray;
uint32_t faceCount;
uint32_t material;
+ ChartType::Enum type;
};
// Output vertex.
diff --git a/version.py b/version.py
index 9184facb73..930981f7af 100644
--- a/version.py
+++ b/version.py
@@ -2,6 +2,7 @@ short_name = "godot"
name = "Godot Engine"
major = 3
minor = 2
+patch = 0
status = "beta"
module_config = ""
year = 2020